Compare commits

...

33 Commits

Author SHA1 Message Date
dan a1016b4275 Improve the output when ".scanstats vm" is enabled.
FossilOrigin-Name: 7df08fd35e9d4bc471aa9fbc4c81d2ebcfd2be6c4c38143342b3d9d727c9df22
2023-07-26 16:41:23 +00:00
dan f8be243fef Add experimental ".scanstats vm" command to the shell tool.
FossilOrigin-Name: e727640fb5c17d23b8e27972065b4acbf169c9240298d3ff7aed092b727d052d
2023-06-30 19:14:35 +00:00
dan e6d7ae24e3 Fix an error in the previous commit on this branch.
FossilOrigin-Name: 47c11ca90f98ffc4d91f07e2ab35826a604a2c903008eeddf8b814bb984971f2
2023-06-30 19:13:27 +00:00
dan aec0aa83a9 Add the "nexec" and "ncycle" columns to the bytecode virtual table. For accessing counters collected when SQLITE_DBCONFIG_STMT_SCANSTATUS is enabled.
FossilOrigin-Name: f7b163a319bee9e935a4abf0bd87e16c9974cba5ae75b0cbba63c9da168f2006
2023-06-30 18:59:10 +00:00
dan 24b368da8d Add support for sqlite3_stmt_scanstatus_v2() profiling of GROUP BY clauses that use a temp b-tree, and for sub-queries implemented as co-routines.
FossilOrigin-Name: 7afad1f759f7ceda873c6d869422fd56fe4399c2d24d47ad9bc3b84b06d830d1
2023-06-30 18:31:37 +00:00
dan 4cd3a59a79 Improve support for sqlite3_stmt_scanstatus_v2() profiling of sub-queries implemented as co-routines.
FossilOrigin-Name: 4e8718dc35dbbaf75f17265a88d14acd9750dc75efbadf41377f9c97e732009c
2023-06-30 18:23:53 +00:00
dan 07d76f7b95 Add support for sqlite3_stmt_scanstatus_v2() profiling of GROUP BY clauses that use a temp b-tree.
FossilOrigin-Name: 796eadcc50e7ea9ec348b1f7e2d6a5a3de78c675a07f665078309e6d81479e7d
2023-06-30 17:14:36 +00:00
dan 1bfe92a691 Add extra debugging code for sqlite3_stmt_scanstatus_v2() to test1.c.
FossilOrigin-Name: f936f101406069b29218c89a36581b4497226fb61906782ea368f12d943c901c
2023-06-30 16:16:51 +00:00
drh 48114d08cf Completely unwind the enhanced precision sum() from [a915f15a916af698] so
as not to offend UBSAN and OSS-Fuzz.

FossilOrigin-Name: 85be05b66ef975f02a3e7b2984bcab97d9280c7f3b6ee1e16718de549f240d46
2023-06-30 14:01:09 +00:00
drh dd8b12a6c5 Omit the doubleToReal() function in vdbemem.c. Use the
equivalent sqlite3RealToI64() function in its place.

FossilOrigin-Name: 625820e8ebfdcf513c81b1b632bbe2aa882a8fbba52001113dc6f56270fa5ceb
2023-06-30 12:59:06 +00:00
drh 60f41362cf Make the sum() function less precise and slower in order to avoid
harmless signed integer overflow UBSAN warnings from OSS-Fuzz.

FossilOrigin-Name: 1be0646a2c352dbf03d2af87fd48b6f9edfd68666790ac6863144ac95f3e0621
2023-06-30 11:51:36 +00:00
drh 2ddfa6a360 Cleanup and commenting of the new DECIMAL extension code. No functional
changes.

FossilOrigin-Name: 5124481663eb8e74a9f861be98adb7075ea911fcff0216d98c658e955acadf14
2023-06-29 23:03:30 +00:00
drh ec3e57fa92 Enhancements to the DECIMAL extension:
(1) If the argument to decimal(X) is a floating point value (or an 8-byte blob),
the floating point value is expanded into its exact decimal representation.
(2) Function decimal_sci(X) works the same except it returns the result in
scientific notation.
(3) New function decimal_pow2(N) returns the full decimal expansion of the N-th
integer power of 2.

FossilOrigin-Name: 8baf8c10aecb261751f2b154356ab224b79d07230929ec9f123791278e601bba
2023-06-29 20:28:03 +00:00
drh 500ca334bd Fix harmless compiler warnings about unused function arguments.
FossilOrigin-Name: 24927c1377314a10177da4a57191593440aa97fd0c5949fdf25a22df1d947600
2023-06-29 17:48:32 +00:00
drh 0b1a1e8c37 Improve the range of floating-point numbers that can be handled as integers
for numeric-to-text conversion.

FossilOrigin-Name: 41580ba452fdbc3f73da60d8030289d38614c4cab8d24140d7cc44a54b2da8d2
2023-06-29 17:36:18 +00:00
drh a75011a891 Further refine the dtostr() testing function in the CLI so that it takes an
optional second parameter which is the number of significant digits to display.

FossilOrigin-Name: 2f9d4444aa503102a00d6e6769dadc57d4b26a2c07f145f23f2f28e0c161246d
2023-06-29 17:26:21 +00:00
drh cd88a74115 Change the (undocumented) dtostr() SQL function in the CLI so that it only
shows the first 26 significant digits - 10 more digits than are available
in a 64-bit double.

FossilOrigin-Name: d758859f6ab94ddb9b3ee6f6f5f24b16e2b7a7712761080cfc6540d68b5a0c97
2023-06-29 16:48:25 +00:00
drh 9ea7632cca Add the decimal_sci(X) function to the Decimal extension for showing a decimal
value in scientific notation:  +D.DDDDDe+DD

FossilOrigin-Name: 61d4923913e88b980ce93db4f3f9f9d7ba3baaac724995c36c9b887c034accdc
2023-06-29 14:49:23 +00:00
drh 7f5fe1faf3 CLI enhancements to facilitate SQLite core testing:
(1) Add built-in functions strtod() and dtostr() that convert text to
floating point and back using C-library routines.
(2) Do not disable all of ".testctrl" without --unsafe-testing, but only
those subcommands of .testctrl that are actually dangerous.

FossilOrigin-Name: 669996a8ddcbf35f3de66cf466508fc1e6dd09ab269aba395ac86a11b2ec238c
2023-06-29 12:14:10 +00:00
drh 8fbb335d9f Enhance the SUM() aggregate (and related AVG() and TOTAL()) so that the running
sum is accurate to about 100 bits.

FossilOrigin-Name: a915f15a916af698e0cef46c8b3e7ed11bda19349179d2d414073cd39c4cce24
2023-06-28 12:02:48 +00:00
drh 60783f47b2 Improved accuracy of floating-point conversion constants as suggested by
[forum:/info/598d32f6135c41c1|forum post 598d32f6135c41c1].

FossilOrigin-Name: 4943e8a1819e189747eefc414d02c0485e1620deff9cf92664295b21a8a9a83c
2023-06-28 11:46:28 +00:00
drh d847c73153 Simple test cases for the enhanced SUM() function.
FossilOrigin-Name: c66ef2440e4e6c7aa17b50e5a29e543713ccab69aa0a415bac29b35b6116504a
2023-06-26 19:57:23 +00:00
drh 12b198f1a2 Use ideas from T. J. Dekker in "A Floating-Point Technique for Extending the
Available Precision" (1971-07-26) to enhance the accuracy of the SUM()
aggregate function in cases where input magnitudes vary wildly.

FossilOrigin-Name: 439fc00fee62b4db3751860485e21a99cae4fd1f5d911b2c08651a1466245ecc
2023-06-26 19:35:20 +00:00
larrybr 502c618f01 Fix CLI .sha3sum error message for keyword identifiers, reported in [forum:/forumpost/7cbe081746dd|forum post 7cbe081746dd].
FossilOrigin-Name: 9d7813ddcf67f1256e7331c5f390cb122b3f7e35cf46e0b33b610216a5396a00
2023-06-26 17:08:08 +00:00
stephan b9561384d0 Replace some JS 'self' references with 'globalThis', as reported via the npm subproject.
FossilOrigin-Name: d4e66dfc2e87112fa73a9c64db358429d88fb2ab3a08908b0eb655f6ed42f94b
2023-06-26 07:05:05 +00:00
drh d2b9cdd592 Fix typo in the README.md file.
FossilOrigin-Name: 6d435d1dace1be52bdb920168e629412b9adf55dbe59cf3db8f169c26f6e6b81
2023-06-25 20:23:51 +00:00
drh cc19bed8b1 Add support for the octet_length() SQL function, with low-level optimizations
that avoid loading large string content from disk when the argument to
octet_length() is a table column.

FossilOrigin-Name: fa5f77862c0fe0189aa4246a1e55bb7c537c28c436ec10b75f5fa141e5e4aff0
2023-06-23 11:10:13 +00:00
drh 077efc2730 Optimize the argument to the octet_length() function so that it does not
attempt to read content from disk.

FossilOrigin-Name: 8b8ea4e3f52d96cc217bd1fb27ca4a83489ef1f250756ed2f790d1b0ee529a3a
2023-06-22 21:19:37 +00:00
drh 7f9dcd664d basic test cases for octet_length().
FossilOrigin-Name: 034a5fe2a0cfe085271385da1d281515b04b311e08962519d03ad8ad156fb4bd
2023-06-22 15:26:52 +00:00
drh d6c671e626 Merge recent trunk enhancements into the octet_length branch.
FossilOrigin-Name: d35c214811aac7dec0000ca2aa77231f74a7963dd0c53cf25a65ade5ef0f8dc0
2023-06-22 13:01:02 +00:00
drh d4170ac0eb Simplification to the getAndInitPage() routine that results in improved
performance.

FossilOrigin-Name: 2e9734c2335d8c06fedc9f4cca02baaf326f7fa276bd464f3214f383715a48d6
2023-06-22 01:03:39 +00:00
drh 71aac8763f Improved comment on the getAndInitPage() in btree.c. No code changes.
FossilOrigin-Name: dc468cfdb825083b3a4b6cb95c913961e9312e22103c5a0cd923b75c83c65e13
2023-06-21 21:47:09 +00:00
drh b3d7f1c2db Prototype implementation of the octet_length() SQL function.
FossilOrigin-Name: 2db989c8635f7e89b3ea58d1fde94787fced039ac1a118d9b6362811eda73f87
2023-06-03 11:22:30 +00:00
24 changed files with 937 additions and 384 deletions
+1 -1
View File
@@ -348,7 +348,7 @@ Or on windows:
> nmake /f Makefile.msc verify-source
Using the makefile to verify source integrity is good for detecting
accidental changes to the source tree, but malecious changes could be
accidental changes to the source tree, but malicious changes could be
hidden by also modifying the makefiles.
## Contacts
+345 -96
View File
@@ -58,41 +58,24 @@ static void decimal_free(Decimal *p){
}
/*
** Allocate a new Decimal object. Initialize it to the number given
** by the input string.
** Allocate a new Decimal object initialized to the text in zIn[].
** Return NULL if any kind of error occurs.
*/
static Decimal *decimal_new(
sqlite3_context *pCtx,
sqlite3_value *pIn,
int nAlt,
const unsigned char *zAlt
){
Decimal *p;
int n, i;
const unsigned char *zIn;
static Decimal *decimalNewFromText(const char *zIn, int n){
Decimal *p = 0;
int i;
int iExp = 0;
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) goto new_no_mem;
if( p==0 ) goto new_from_text_failed;
p->sign = 0;
p->oom = 0;
p->isInit = 1;
p->isNull = 0;
p->nDigit = 0;
p->nFrac = 0;
if( zAlt ){
n = nAlt,
zIn = zAlt;
}else{
if( sqlite3_value_type(pIn)==SQLITE_NULL ){
p->a = 0;
p->isNull = 1;
return p;
}
n = sqlite3_value_bytes(pIn);
zIn = sqlite3_value_text(pIn);
}
p->a = sqlite3_malloc64( n+1 );
if( p->a==0 ) goto new_no_mem;
if( p->a==0 ) goto new_from_text_failed;
for(i=0; isspace(zIn[i]); i++){}
if( zIn[i]=='-' ){
p->sign = 1;
@@ -143,7 +126,7 @@ static Decimal *decimal_new(
}
if( iExp>0 ){
p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
if( p->a==0 ) goto new_no_mem;
if( p->a==0 ) goto new_from_text_failed;
memset(p->a+p->nDigit, 0, iExp);
p->nDigit += iExp;
}
@@ -162,7 +145,7 @@ static Decimal *decimal_new(
}
if( iExp>0 ){
p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
if( p->a==0 ) goto new_no_mem;
if( p->a==0 ) goto new_from_text_failed;
memmove(p->a+iExp, p->a, p->nDigit);
memset(p->a, 0, iExp);
p->nDigit += iExp;
@@ -171,7 +154,76 @@ static Decimal *decimal_new(
}
return p;
new_no_mem:
new_from_text_failed:
if( p ){
if( p->a ) sqlite3_free(p->a);
sqlite3_free(p);
}
return 0;
}
/* Forward reference */
static Decimal *decimalFromDouble(double);
/*
** Allocate a new Decimal object from an sqlite3_value. Return a pointer
** to the new object, or NULL if there is an error. If the pCtx argument
** is not NULL, then errors are reported on it as well.
**
** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted
** directly into a Decimal. For SQLITE_FLOAT or for SQLITE_BLOB of length
** 8 bytes, the resulting double value is expanded into its decimal equivalent.
** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length,
** then NULL is returned.
*/
static Decimal *decimal_new(
sqlite3_context *pCtx, /* Report error here, if not null */
sqlite3_value *pIn, /* Construct the decimal object from this */
int bTextOnly /* Always interpret pIn as text if true */
){
Decimal *p = 0;
int eType = sqlite3_value_type(pIn);
if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){
eType = SQLITE_TEXT;
}
switch( eType ){
case SQLITE_TEXT:
case SQLITE_INTEGER: {
const char *zIn = (const char*)sqlite3_value_text(pIn);
int n = sqlite3_value_bytes(pIn);
p = decimalNewFromText(zIn, n);
if( p==0 ) goto new_failed;
break;
}
case SQLITE_FLOAT: {
p = decimalFromDouble(sqlite3_value_double(pIn));
break;
}
case SQLITE_BLOB: {
const unsigned char *x;
unsigned int i;
sqlite3_uint64 v = 0;
double r;
if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break;
x = sqlite3_value_blob(pIn);
for(i=0; i<sizeof(r); i++){
v = (v<<8) | x[i];
}
memcpy(&r, &v, sizeof(r));
p = decimalFromDouble(r);
break;
}
case SQLITE_NULL: {
break;
}
}
return p;
new_failed:
if( pCtx ) sqlite3_result_error_nomem(pCtx);
sqlite3_free(p);
return 0;
@@ -231,19 +283,64 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
}
/*
** SQL Function: decimal(X)
**
** Convert input X into decimal and then back into text
** Make the given Decimal the result in an format similar to '%+#e'.
** In other words, show exponential notation with leading and trailing
** zeros omitted.
*/
static void decimalFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *p = decimal_new(context, argv[0], 0, 0);
UNUSED_PARAMETER(argc);
decimal_result(context, p);
decimal_free(p);
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
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 */
signed char zero; /* Zero value */
signed char *a; /* Array of digits */
if( p==0 || p->oom ){
sqlite3_result_error_nomem(pCtx);
return;
}
if( p->isNull ){
sqlite3_result_null(pCtx);
return;
}
for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){}
for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
nFrac = p->nFrac + (nDigit - p->nDigit);
nDigit -= nZero;
z = sqlite3_malloc( nDigit+20 );
if( z==0 ){
sqlite3_result_error_nomem(pCtx);
return;
}
if( nDigit==0 ){
zero = 0;
a = &zero;
nDigit = 1;
nFrac = 0;
}else{
a = &p->a[nZero];
}
if( p->sign && nDigit>0 ){
z[0] = '-';
}else{
z[0] = '+';
}
z[1] = a[0]+'0';
z[2] = '.';
if( nDigit==1 ){
z[3] = '0';
i = 4;
}else{
for(i=1; i<nDigit; i++){
z[2+i] = a[i]+'0';
}
i = nDigit+2;
}
exp = nDigit - nFrac - 1;
sqlite3_snprintf(nDigit+20-i, &z[i], "e%+03d", exp);
sqlite3_result_text(pCtx, z, -1, sqlite3_free);
}
/*
@@ -296,9 +393,9 @@ static void decimalCmpFunc(
int rc;
UNUSED_PARAMETER(argc);
pA = decimal_new(context, argv[0], 0, 0);
pA = decimal_new(context, argv[0], 1);
if( pA==0 || pA->isNull ) goto cmp_done;
pB = decimal_new(context, argv[1], 0, 0);
pB = decimal_new(context, argv[1], 1);
if( pB==0 || pB->isNull ) goto cmp_done;
rc = decimal_cmp(pA, pB);
if( rc<0 ) rc = -1;
@@ -338,7 +435,7 @@ static void decimal_expand(Decimal *p, int nDigit, int nFrac){
}
/*
** Add the value pB into pA.
** Add the value pB into pA. A := A + B.
**
** Both pA and pB might become denormalized by this routine.
*/
@@ -407,6 +504,172 @@ static void decimal_add(Decimal *pA, Decimal *pB){
}
}
/*
** Multiply A by B. A := A * B
**
** All significant digits after the decimal point are retained.
** Trailing zeros after the decimal point are omitted as long as
** the number of digits after the decimal point is no less than
** either the number of digits in either input.
*/
static void decimalMul(Decimal *pA, Decimal *pB){
signed char *acc = 0;
int i, j, k;
int minFrac;
if( pA==0 || pA->oom || pA->isNull
|| pB==0 || pB->oom || pB->isNull
){
goto mul_end;
}
acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
if( acc==0 ){
pA->oom = 1;
goto mul_end;
}
memset(acc, 0, pA->nDigit + pB->nDigit + 2);
minFrac = pA->nFrac;
if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
for(i=pA->nDigit-1; i>=0; i--){
signed char f = pA->a[i];
int carry = 0, x;
for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
x = acc[k] + f*pB->a[j] + carry;
acc[k] = x%10;
carry = x/10;
}
x = acc[k] + carry;
acc[k] = x%10;
acc[k-1] += x/10;
}
sqlite3_free(pA->a);
pA->a = acc;
acc = 0;
pA->nDigit += pB->nDigit + 2;
pA->nFrac += pB->nFrac;
pA->sign ^= pB->sign;
while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
pA->nFrac--;
pA->nDigit--;
}
mul_end:
sqlite3_free(acc);
}
/*
** Create a new Decimal object that contains an integer power of 2.
*/
static Decimal *decimalPow2(int N){
Decimal *pA = 0; /* The result to be returned */
Decimal *pX = 0; /* Multiplier */
if( N<-20000 || N>20000 ) goto pow2_fault;
pA = decimalNewFromText("1.0", 3);
if( pA==0 || pA->oom ) goto pow2_fault;
if( N==0 ) return pA;
if( N>0 ){
pX = decimalNewFromText("2.0", 3);
}else{
N = -N;
pX = decimalNewFromText("0.5", 3);
}
if( pX==0 || pX->oom ) goto pow2_fault;
while( 1 /* Exit by break */ ){
if( N & 1 ){
decimalMul(pA, pX);
if( pA->oom ) goto pow2_fault;
}
N >>= 1;
if( N==0 ) break;
decimalMul(pX, pX);
}
decimal_free(pX);
return pA;
pow2_fault:
decimal_free(pA);
decimal_free(pX);
return 0;
}
/*
** Use an IEEE754 binary64 ("double") to generate a new Decimal object.
*/
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 ){
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 ){
return 0; /* 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;
}
/*
** SQL Function: decimal(X)
** OR: decimal_sci(X)
**
** Convert input X into decimal and then back into text.
**
** If X is originally a float, then a full decimal expansion of that floating
** point value is done. Or if X is an 8-byte blob, it is interpreted
** as a float and similarly expanded.
**
** The decimal_sci(X) function returns the result in scientific notation.
** decimal(X) returns a complete decimal, without the e+NNN at the end.
*/
static void decimalFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *p = decimal_new(context, argv[0], 0);
UNUSED_PARAMETER(argc);
if( p ){
if( sqlite3_user_data(context)!=0 ){
decimal_result_sci(context, p);
}else{
decimal_result(context, p);
}
decimal_free(p);
}
}
/*
** Compare text in decimal order.
*/
@@ -417,8 +680,8 @@ static int decimalCollFunc(
){
const unsigned char *zA = (const unsigned char*)pKey1;
const unsigned char *zB = (const unsigned char*)pKey2;
Decimal *pA = decimal_new(0, 0, nKey1, zA);
Decimal *pB = decimal_new(0, 0, nKey2, zB);
Decimal *pA = decimalNewFromText((const char*)zA, nKey1);
Decimal *pB = decimalNewFromText((const char*)zB, nKey2);
int rc;
UNUSED_PARAMETER(notUsed);
if( pA==0 || pB==0 ){
@@ -443,8 +706,8 @@ static void decimalAddFunc(
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
Decimal *pA = decimal_new(context, argv[0], 1);
Decimal *pB = decimal_new(context, argv[1], 1);
UNUSED_PARAMETER(argc);
decimal_add(pA, pB);
decimal_result(context, pA);
@@ -456,8 +719,8 @@ static void decimalSubFunc(
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
Decimal *pA = decimal_new(context, argv[0], 1);
Decimal *pB = decimal_new(context, argv[1], 1);
UNUSED_PARAMETER(argc);
if( pB ){
pB->sign = !pB->sign;
@@ -495,7 +758,7 @@ static void decimalSumStep(
p->nFrac = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pArg = decimal_new(context, argv[0], 0, 0);
pArg = decimal_new(context, argv[0], 1);
decimal_add(p, pArg);
decimal_free(pArg);
}
@@ -510,7 +773,7 @@ static void decimalSumInverse(
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p==0 ) return;
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pArg = decimal_new(context, argv[0], 0, 0);
pArg = decimal_new(context, argv[0], 1);
if( pArg ) pArg->sign = !pArg->sign;
decimal_add(p, pArg);
decimal_free(pArg);
@@ -531,66 +794,49 @@ static void decimalSumFinalize(sqlite3_context *context){
** SQL Function: decimal_mul(X, Y)
**
** Return the product of X and Y.
**
** All significant digits after the decimal point are retained.
** Trailing zeros after the decimal point are omitted as long as
** the number of digits after the decimal point is no less than
** either the number of digits in either input.
*/
static void decimalMulFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
signed char *acc = 0;
int i, j, k;
int minFrac;
Decimal *pA = decimal_new(context, argv[0], 1);
Decimal *pB = decimal_new(context, argv[1], 1);
UNUSED_PARAMETER(argc);
if( pA==0 || pA->oom || pA->isNull
|| pB==0 || pB->oom || pB->isNull
){
goto mul_end;
}
acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
if( acc==0 ){
sqlite3_result_error_nomem(context);
decimalMul(pA, pB);
if( pA->oom ){
goto mul_end;
}
memset(acc, 0, pA->nDigit + pB->nDigit + 2);
minFrac = pA->nFrac;
if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
for(i=pA->nDigit-1; i>=0; i--){
signed char f = pA->a[i];
int carry = 0, x;
for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
x = acc[k] + f*pB->a[j] + carry;
acc[k] = x%10;
carry = x/10;
}
x = acc[k] + carry;
acc[k] = x%10;
acc[k-1] += x/10;
}
sqlite3_free(pA->a);
pA->a = acc;
acc = 0;
pA->nDigit += pB->nDigit + 2;
pA->nFrac += pB->nFrac;
pA->sign ^= pB->sign;
while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
pA->nFrac--;
pA->nDigit--;
}
decimal_result(context, pA);
mul_end:
sqlite3_free(acc);
decimal_free(pA);
decimal_free(pB);
}
/*
** SQL Function: decimal_pow2(N)
**
** Return the N-th power of 2. N must be an integer.
*/
static void decimalPow2Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
Decimal *pA = decimalPow2(sqlite3_value_int(argv[0]));
decimal_result_sci(context, pA);
decimal_free(pA);
}
}
#ifdef _WIN32
__declspec(dllexport)
#endif
@@ -603,13 +849,16 @@ int sqlite3_decimal_init(
static const struct {
const char *zFuncName;
int nArg;
int iArg;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "decimal", 1, decimalFunc },
{ "decimal_cmp", 2, decimalCmpFunc },
{ "decimal_add", 2, decimalAddFunc },
{ "decimal_sub", 2, decimalSubFunc },
{ "decimal_mul", 2, decimalMulFunc },
{ "decimal", 1, 0, decimalFunc },
{ "decimal_sci", 1, 1, decimalFunc },
{ "decimal_cmp", 2, 0, decimalCmpFunc },
{ "decimal_add", 2, 0, decimalAddFunc },
{ "decimal_sub", 2, 0, decimalSubFunc },
{ "decimal_mul", 2, 0, decimalMulFunc },
{ "decimal_pow2", 1, 0, decimalPow2Func },
};
unsigned int i;
(void)pzErrMsg; /* Unused parameter */
@@ -619,7 +868,7 @@ int sqlite3_decimal_init(
for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, aFunc[i].xFunc, 0, 0);
aFunc[i].iArg ? db : 0, aFunc[i].xFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_window_function(db, "decimal_sum", 1,
+3 -3
View File
@@ -174,7 +174,7 @@
globalThis.WhWasmUtilInstaller = function(target){
'use strict';
if(undefined===target.bigIntEnabled){
target.bigIntEnabled = !!self['BigInt64Array'];
target.bigIntEnabled = !!globalThis['BigInt64Array'];
}
/** Throws a new Error, the message of which is the concatenation of
@@ -355,8 +355,8 @@ globalThis.WhWasmUtilInstaller = function(target){
break;
default:
if(target.bigIntEnabled){
if(n===self['BigUint64Array']) return c.HEAP64U;
else if(n===self['BigInt64Array']) return c.HEAP64;
if(n===globalThis['BigUint64Array']) return c.HEAP64U;
else if(n===globalThis['BigInt64Array']) return c.HEAP64;
break;
}
}
+3 -3
View File
@@ -60,9 +60,9 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
memberPrefix = (config.memberPrefix || ""),
memberSuffix = (config.memberSuffix || ""),
bigIntEnabled = (undefined===config.bigIntEnabled
? !!self['BigInt64Array'] : !!config.bigIntEnabled),
BigInt = self['BigInt'],
BigInt64Array = self['BigInt64Array'],
? !!globalThis['BigInt64Array'] : !!config.bigIntEnabled),
BigInt = globalThis['BigInt'],
BigInt64Array = globalThis['BigInt64Array'],
/* Undocumented (on purpose) config options: */
ptrSizeof = config.ptrSizeof || 4,
ptrIR = config.ptrIR || 'i32'
+28 -28
View File
@@ -1,12 +1,12 @@
C Add\sthe\s--pcachetrace\soption\sto\sthe\sCLI.
D 2023-06-21T14:11:25.888
C Improve\sthe\soutput\swhen\s".scanstats\svm"\sis\senabled.
D 2023-07-26T16:41:23.325
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc 7248d860f71ab164b4cec3c415e6cc1bd9fee860c370d65bd8bb49e9572521e2
F README.md 8ff80689b9cb9f6e9b842edf31a3358ff53bc538c351799e03dd3e5455e637e5
F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224
F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -287,7 +287,7 @@ F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8b
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
F ext/misc/csv.c ca8d6dafc5469639de81937cb66ae2e6b358542aba94c4f791910d355a8e7f73
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
F ext/misc/decimal.c 57d85fa20a5a74d3b0dfc78ab7934ae6c9f5aa8eed915faa2b5246bec87ddc6d
F ext/misc/decimal.c a61343b36672760e1d6d5b20a42cb52264db55bcd11d0a44e2e06e8ce23227e3
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebfb720
@@ -513,7 +513,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
F ext/wasm/common/whwasmutil.js 749a1f81f85835e9a384e9706f2a955a7158f2b8cc9da33f41105cac7775a305
F ext/wasm/common/whwasmutil.js 03407d7b61b817fd135c82401987e56688a45ee4d6b9c0eced160c0000d6e4c2
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@@ -532,7 +532,7 @@ F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e
F ext/wasm/index.html dd900891844caebd9cadbddd704f66bd841d7c12fd69ce5af490e2c10fb49f45
F ext/wasm/jaccwabyt/jaccwabyt.js 8287c0537fa0750414edbe75ce64668a81c8716df5ec4c3e6bb4f11bd1c36031
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
@@ -576,7 +576,7 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c 481666a3dd26b1cb16a9e9baaa3f6b17cab52a1d7a5836e5dcf5b45b85d4a51d
F src/btree.c c0c93b6cb4dc133b528c1290bb4ad0f2414452f9a5758ff2b106af718874f39e
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
@@ -587,10 +587,10 @@ F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
F src/delete.c cd5f5cd06ed0b6a882ec1a8c2a0d73b3cecb28479ad19e9931c4706c5e2182be
F src/expr.c 36f6a47c8a2c20ec3c267a60fc598857876edd60af0cb40caf7b69b651fd73bf
F src/expr.c 8d1656b65e26af3e34f78e947ac423f0d20c214ed25a67486e433bf16ca6b543
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
F src/func.c 6303e1ccb80dbd0d9b52f902a01d3b105981486fdfd66f9e1ddfd74aaf3032fc
F src/func.c 6b4804738b4d869f40625958b476a8f964d3df65b626e72a530d76051863cf32
F src/global.c bd0892ade7289f6e20bff44c07d06371f2ff9b53cea359e7854b9b72f65adc30
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -633,21 +633,21 @@ F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
F src/pragma.c 37b8fb02d090262280c86e1e2654bf59d8dbfbfe8dc6733f2b968a11374c095a
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c d6c4354f8ea0dc06962fbabc4b68c4471a45276a2918c929be00f9f537f69eb1
F src/printf.c b9320cdbeca0b336c3f139fd36dd121e4167dd62b35fbe9ccaa9bab44c0af38d
F src/printf.c a87473be34fa2acafa27692b8ae078275c7e23360956c93c07ff22f5d609cbd7
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 383b9dba12493c365ee2036bcadd73013b7c0f7d2afcda0c378317c335d60ac2
F src/shell.c.in bdd1fdfc77a67651cdc5a158bc9107cf3c2cf3ddb62d7a4da06c6eaaa5e72037
F src/select.c 3ab1186290a311a8ceed1286c0e286209f7fe97b2d02c7593258004ce295dd88
F src/shell.c.in 921831fe4acca388f66472f6e4076c4531edf17b1b0a64d85843606f339d00d3
F src/sqlite.h.in 3076d78836b6dac53b3ab0875fc8fd15bca8077aad4d33c85336e05af6aef8c7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqliteInt.h 8974b60740b108269f51e833e85191be6bf9f06f317ee34a53b7ec215762cf8c
F src/sqliteInt.h b677ba33397479f9a2fa1223fcd24b561cc8c77c7d073798f7b7118e15d69dbb
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
F src/test1.c e6ab4a00671f052366a01bcb7fdf2e2f6bb4aa884cd01e738c5590dcf47a99ca
F src/test1.c 64b8462099618a6243f63ba701eea8913046cd7377a7a77a7e3a0ada42219275
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@@ -705,18 +705,18 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 6f9d2f278dcc8d41c618980cd3cfe88e1bafc0626209b917c6773d8202d29ef6
F src/util.c 4264102045fdb36e9af3ff361e390a5f7a76342a2bd7069e55d8ad332026d6b5
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c 6c0de640ef3be08cf2992d588a7501aee0f1003027bc952a6916a35f6e33b4cf
F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
F src/vdbeInt.h 7bd49eef8f89c1a271fbf12d80a206bf56c876814c5fc6bee340f4e1907095ae
F src/vdbeapi.c de9703f8705afc393cc2864669ce28cf9516983c8331d59aa2b978de01634365
F src/vdbeaux.c 4d5e68a3850d0b193a692eca6442d7afe35252aaf29728a67adcb542ecabd9ce
F src/vdbeaux.c b5e3f7e158518b4eca6f166ac43900640a3fe9735c710e12bfa119af21059339
F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
F src/vdbemem.c 710119a8e35e47813681c48703d65a80ba22792192de90bc51dc0d6366f2a79e
F src/vdbemem.c aed58a560caab12540f7c14c43ee188636017814e21247a97902f78de2d43117
F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
F src/vdbevtab.c 57fa8f56478e5b5cb558cb425e7878515e0a105c54f96f1d1bbf4b9433529254
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c cbfeeb7415baa545efa244dd34bb5af4ae953a206fed720c6fa7f1ef763ec122
@@ -724,7 +724,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93
F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a
F src/wherecode.c bff0bc56cb1a382de266c2db3a691135c18a4360b6ad5e069e5c415d57eb0c38
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
F src/window.c b7ad9cff3ce8ae6f8cc25e18e1a258426cb6bd2999aace6f5248d781b2a74098
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -939,7 +939,7 @@ F test/dbpage.test fce29035c7566fd7835ec0f19422cb4b9c6944ce0e1b936ff8452443f92e8
F test/dbpagefault.test d9111a62f3601d3efc6841ace3940181937342d245f92a1cca6cba8206d4f58a
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
F test/decimal.test 18e7b4cb12e8d5c60d768b686ba52af3e1ca3ced4f870231f0476666fd9fab7e
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -1107,7 +1107,7 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 4be8bed4be235e333f1e0ea31e32f5be3c9f456c30780363e7fcb15e3ff3e6bc
F test/func.test f246a12169d1b0dbebcf70bb4ad0324b12e8fdbfbbbcc1c92379c7088014c602
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
@@ -1425,7 +1425,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
F test/scanstatus.test b249328caf4d317e71058006872b8012598a5fa045b30bf24a81eeff650ab49e
F test/scanstatus2.test 9a00becb1d60d168944f8e2f3585d44d46123aa95c5c7c25563309e1f15f924d
F test/scanstatus2.test d0434bc3b356fb9d948f3417846b2ed5bbc4bd4cc49bddb38ac86469f754bfb0
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
@@ -1469,7 +1469,7 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 300b77328aaafb9f3e7a53a26e4162fbf92181d92251d259ff105a2275ff998d
F test/shell2.test 09a202f57e7cd99788537f763e0845796a173fcea06a0d199a08d69446fe1daf
F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
@@ -2041,8 +2041,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P f94f3021cde1d46373ee8fc8e5028d7507a937240c59cf0d0d19ab22acbd3c41
R d23fbd106a98c76f065fa8c0590bcfbb
U drh
Z 6142bb2a618d1d23b62eb525e555db78
P e727640fb5c17d23b8e27972065b4acbf169c9240298d3ff7aed092b727d052d
R cd10daa978b5e0a84d84b4bb41300995
U dan
Z 2a26d9e4014ba821912c8a2a17121583
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1
7df08fd35e9d4bc471aa9fbc4c81d2ebcfd2be6c4c38143342b3d9d727c9df22
+59 -50
View File
@@ -2318,68 +2318,41 @@ Pgno sqlite3BtreeLastPage(Btree *p){
/*
** Get a page from the pager and initialize it.
**
** If pCur!=0 then the page is being fetched as part of a moveToChild()
** call. Do additional sanity checking on the page in this case.
** And if the fetch fails, this routine must decrement pCur->iPage.
**
** The page is fetched as read-write unless pCur is not NULL and is
** a read-only cursor.
**
** If an error occurs, then *ppPage is undefined. It
** may remain unchanged, or it may be set to an invalid value.
*/
static int getAndInitPage(
BtShared *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
MemPage **ppPage, /* Write the page pointer here */
BtCursor *pCur, /* Cursor to receive the page, or NULL */
int bReadOnly /* True for a read-only page */
){
int rc;
DbPage *pDbPage;
MemPage *pPage;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pCur==0 || ppPage==&pCur->pPage );
assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
assert( pCur==0 || pCur->iPage>0 );
if( pgno>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
goto getAndInitPage_error1;
*ppPage = 0;
return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
if( rc ){
goto getAndInitPage_error1;
*ppPage = 0;
return rc;
}
*ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
if( (*ppPage)->isInit==0 ){
pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
if( pPage->isInit==0 ){
btreePageFromDbPage(pDbPage, pgno, pBt);
rc = btreeInitPage(*ppPage);
rc = btreeInitPage(pPage);
if( rc!=SQLITE_OK ){
goto getAndInitPage_error2;
releasePage(pPage);
*ppPage = 0;
return rc;
}
}
assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
/* If obtaining a child page for a cursor, we must verify that the page is
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
rc = SQLITE_CORRUPT_PGNO(pgno);
goto getAndInitPage_error2;
}
assert( pPage->pgno==pgno || CORRUPT_DB );
assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
*ppPage = pPage;
return SQLITE_OK;
getAndInitPage_error2:
releasePage(*ppPage);
getAndInitPage_error1:
if( pCur ){
pCur->iPage--;
pCur->pPage = pCur->apPage[pCur->iPage];
}
testcase( pgno==0 );
assert( pgno!=0 || rc!=SQLITE_OK );
return rc;
}
/*
@@ -5353,6 +5326,7 @@ const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
** vice-versa).
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
@@ -5366,8 +5340,17 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur,
pCur->curPagerFlags);
rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags);
if( rc==SQLITE_OK
&& (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
){
releasePage(pCur->pPage);
rc = SQLITE_CORRUPT_PGNO(newPgno);
}
if( rc ){
pCur->pPage = pCur->apPage[--pCur->iPage];
}
return rc;
}
#ifdef SQLITE_DEBUG
@@ -5474,7 +5457,7 @@ static int moveToRoot(BtCursor *pCur){
sqlite3BtreeClearCursor(pCur);
}
rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
0, pCur->curPagerFlags);
pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ -6087,10 +6070,36 @@ bypass_moveto_root:
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
pCur->ix = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
/* This block is similar to an in-lined version of:
**
** pCur->ix = (u16)lwr;
** rc = moveToChild(pCur, chldPg);
** if( rc ) break;
*/
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
return SQLITE_CORRUPT_BKPT;
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags);
if( rc==SQLITE_OK
&& (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
){
releasePage(pCur->pPage);
rc = SQLITE_CORRUPT_PGNO(chldPg);
}
if( rc ){
pCur->pPage = pCur->apPage[--pCur->iPage];
break;
}
/*
***** End of in-lined moveToChild() call */
}
moveto_index_finish:
pCur->info.nSize = 0;
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
@@ -8144,7 +8153,7 @@ static int balance_nonroot(
pgno = get4byte(pRight);
while( 1 ){
if( rc==SQLITE_OK ){
rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
}
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
@@ -10029,7 +10038,7 @@ static int clearDatabasePage(
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
&& sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
+9 -6
View File
@@ -4668,10 +4668,10 @@ expr_code_doover:
r1 = sqlite3GetTempRange(pParse, nFarg);
}
/* For length() and typeof() functions with a column argument,
/* For length() and typeof() and octet_length() functions,
** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
** loading.
** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid
** unnecessary data loading.
*/
if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
u8 exprOp;
@@ -4681,9 +4681,12 @@ expr_code_doover:
if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
pFarg->a[0].pExpr->op2 =
pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
assert( SQLITE_FUNC_BYTELEN==OPFLAG_BYTELENARG );
assert( (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG)==OPFLAG_BYTELENARG );
testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_LENGTHARG );
testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_TYPEOFARG );
testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_BYTELENARG);
pFarg->a[0].pExpr->op2 = pDef->funcFlags & OPFLAG_BYTELENARG;
}
}
+83 -23
View File
@@ -149,6 +149,42 @@ static void lengthFunc(
}
}
/*
** Implementation of the octet_length() function
*/
static void bytelengthFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_BLOB: {
sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
break;
}
case SQLITE_INTEGER:
case SQLITE_FLOAT: {
i64 m = sqlite3_context_db_handle(context)->enc<=SQLITE_UTF8 ? 1 : 2;
sqlite3_result_int64(context, sqlite3_value_bytes(argv[0])*m);
break;
}
case SQLITE_TEXT: {
if( sqlite3_value_encoding(argv[0])<=SQLITE_UTF8 ){
sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
}else{
sqlite3_result_int(context, sqlite3_value_bytes16(argv[0]));
}
break;
}
default: {
sqlite3_result_null(context);
break;
}
}
}
/*
** Implementation of the abs() function.
**
@@ -1634,11 +1670,11 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
*/
typedef struct SumCtx SumCtx;
struct SumCtx {
double rSum; /* Floating point sum */
i64 iSum; /* Integer sum */
double rSum; /* Running sum as as a double */
i64 iSum; /* Running sum as a signed integer */
i64 cnt; /* Number of elements summed */
u8 overflow; /* True if integer overflow seen */
u8 approx; /* True if non-integer value was input to the sum */
u8 approx; /* True if any non-integer value was input to the sum */
u8 ovrfl; /* Integer overflow seen */
};
/*
@@ -1660,15 +1696,26 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
type = sqlite3_value_numeric_type(argv[0]);
if( p && type!=SQLITE_NULL ){
p->cnt++;
if( type==SQLITE_INTEGER ){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
p->approx = p->overflow = 1;
if( p->approx==0 ){
if( type!=SQLITE_INTEGER ){
p->rSum = (double)p->iSum;
p->approx = 1;
p->rSum += sqlite3_value_double(argv[0]);
}else{
i64 x = p->iSum;
if( sqlite3AddInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
p->iSum = x;
}else{
p->ovrfl = 1;
p->rSum = (double)p->iSum;
p->approx = 1;
p->rSum += sqlite3_value_double(argv[0]);
}
}
}else{
p->rSum += sqlite3_value_double(argv[0]);
if( type!=SQLITE_INTEGER ) p->ovrfl = 0;
p->approx = 1;
p->rSum += sqlite3_value_double(argv[0]);
}
}
}
@@ -1685,13 +1732,10 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
if( ALWAYS(p) && type!=SQLITE_NULL ){
assert( p->cnt>0 );
p->cnt--;
assert( type==SQLITE_INTEGER || p->approx );
if( type==SQLITE_INTEGER && p->approx==0 ){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum -= v;
p->iSum -= v;
}else{
if( p->approx ){
p->rSum -= sqlite3_value_double(argv[0]);
}else{
p->iSum -= sqlite3_value_int64(argv[0]);
}
}
}
@@ -1702,10 +1746,12 @@ static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
if( p->overflow ){
sqlite3_result_error(context,"integer overflow",-1);
}else if( p->approx ){
sqlite3_result_double(context, p->rSum);
if( p->approx ){
if( p->ovrfl ){
sqlite3_result_error(context,"integer overflow",-1);
}else{
sqlite3_result_double(context, p->rSum);
}
}else{
sqlite3_result_int64(context, p->iSum);
}
@@ -1715,14 +1761,27 @@ static void avgFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
sqlite3_result_double(context, p->rSum/(double)p->cnt);
double r;
if( p->approx ){
r = p->rSum;
}else{
r = sqlite3RealToI64(p->iSum);
}
sqlite3_result_double(context, r/(double)p->cnt);
}
}
static void totalFinalize(sqlite3_context *context){
SumCtx *p;
double r = 0.0;
p = sqlite3_aggregate_context(context, 0);
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
sqlite3_result_double(context, p ? p->rSum : (double)0);
if( p ){
if( p->approx ){
r = p->rSum;
}else{
r = sqlite3RealToI64(p->iSum);
}
}
sqlite3_result_double(context, r);
}
/*
@@ -2376,6 +2435,7 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN),
FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(printf, -1, 0, 0, printfFunc ),
FUNCTION(format, -1, 0, 0, printfFunc ),
+7 -7
View File
@@ -559,7 +559,7 @@ void sqlite3_str_vappendf(
exp = 0;
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );
if( realvalue<1.0e+16
if( realvalue<9.22e+18
&& realvalue==(LONGDOUBLE_TYPE)(longvalue = (u64)realvalue)
){
/* Number is a pure integer that can be represented as u64 */
@@ -598,13 +598,13 @@ void sqlite3_str_vappendf(
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
if( ALWAYS(realvalue>0.0) ){
LONGDOUBLE_TYPE scale = 1.0;
while( realvalue>=1e100*scale && exp<=350){ scale*=1e100;exp+=100;}
while( realvalue>=1e10*scale && exp<=350 ){ scale*=1e10; exp+=10; }
while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
LONGDOUBLE_TYPE scale = 1.0L;
while( realvalue>=1e100*scale && exp<=350){ scale*=1e100L;exp+=100;}
while( realvalue>=1e10*scale && exp<=350 ){ scale*=1e10L; exp+=10; }
while( realvalue>=10.0*scale && exp<=350 ){ scale*=10.0L; exp++; }
realvalue /= scale;
while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
while( realvalue<1e-8 ){ realvalue *= 1e8L; exp-=8; }
while( realvalue<1.0 ){ realvalue *= 10.0L; exp--; }
if( exp>350 ){
if( flag_zeropad ){
realvalue = 9.0;
+11 -2
View File
@@ -8009,9 +8009,13 @@ int sqlite3Select(
int nCol;
int nGroupBy;
explainTempTable(pParse,
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrExp; /* Address of OP_Explain instruction */
#endif
ExplainQueryPlan2(addrExp, (pParse, 0, "USE TEMP B-TREE FOR %s",
(sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
"DISTINCT" : "GROUP BY");
"DISTINCT" : "GROUP BY"
));
groupBySort = 1;
nGroupBy = pGroupBy->nExpr;
@@ -8036,18 +8040,23 @@ int sqlite3Select(
}
pAggInfo->directMode = 0;
regRecord = sqlite3GetTempReg(pParse);
sqlite3VdbeScanStatusCounters(v, addrExp, 0, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlite3VdbeScanStatusRange(v, addrExp, sqlite3VdbeCurrentAddr(v)-2, -1);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
TREETRACE(0x2,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlite3GetTempReg(pParse);
sqlite3VdbeScanStatusCounters(v, addrExp, sqlite3VdbeCurrentAddr(v), 0);
sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
pAggInfo->useSortingIdx = 1;
sqlite3VdbeScanStatusRange(v, addrExp, -1, sortPTab);
sqlite3VdbeScanStatusRange(v, addrExp, -1, pAggInfo->sortingIdx);
}
/* If there are entries in pAgggInfo->aFunc[] that contain subexpressions
+155 -76
View File
@@ -1207,6 +1207,46 @@ static char *shellFakeSchema(
return s.z;
}
/*
** 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
** routines against the C-library.
*/
static void shellStrtod(
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
char *z = (char*)sqlite3_value_text(apVal[0]);
UNUSED_PARAMETER(nVal);
if( z==0 ) return;
sqlite3_result_double(pCtx, strtod(z,0));
}
/*
** SQL function: dtostr(X)
**
** Use the C-library printf() function to convert real value X into a string.
** Used for comparing the accuracy of SQLite's internal float-to-text conversion
** routines against the C-library.
*/
static void shellDtostr(
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
double r = sqlite3_value_double(apVal[0]);
int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
char z[400];
if( n<1 ) n = 1;
if( n>350 ) n = 350;
sprintf(z, "%#+.*e", n, r);
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}
/*
** SQL function: shell_module_schema(X)
**
@@ -1567,6 +1607,7 @@ static ShellState shellState;
#define MODE_Box 16 /* Unicode box-drawing characters */
#define MODE_Count 17 /* Output only a count of the rows of output */
#define MODE_Off 18 /* No query output shown */
#define MODE_ScanExp 19 /* Like MODE_Explain, but for ".scanstats vm" */
static const char *modeDescr[] = {
"line",
@@ -2480,38 +2521,58 @@ static int shell_callback(
}
break;
}
case MODE_ScanExp:
case MODE_Explain: {
static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
if( nArg>ArraySize(aExplainWidth) ){
nArg = ArraySize(aExplainWidth);
static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 };
static const int aScanExpWidth[] = {4, 6, 6, 13, 4, 4, 4, 13, 2, 13};
static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 };
const int *aWidth = aExplainWidth;
const int *aMap = aExplainMap;
int nWidth = ArraySize(aExplainWidth);
int iIndent = 1;
if( p->cMode==MODE_ScanExp ){
aWidth = aScanExpWidth;
aMap = aScanExpMap;
nWidth = ArraySize(aScanExpWidth);
iIndent = 3;
}
if( nArg>nWidth ) nArg = nWidth;
/* If this is the first row seen, print out the headers */
if( p->cnt++==0 ){
for(i=0; i<nArg; i++){
int w = aExplainWidth[i];
utf8_width_print(p->out, w, azCol[i]);
utf8_width_print(p->out, aWidth[i], azCol[ aMap[i] ]);
fputs(i==nArg-1 ? "\n" : " ", p->out);
}
for(i=0; i<nArg; i++){
int w = aExplainWidth[i];
print_dashes(p->out, w);
print_dashes(p->out, aWidth[i]);
fputs(i==nArg-1 ? "\n" : " ", p->out);
}
}
/* If there is no data, exit early. */
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int w = aExplainWidth[i];
const char *zSep = " ";
int w = aWidth[i];
const char *zVal = azArg[ aMap[i] ];
if( i==nArg-1 ) w = 0;
if( azArg[i] && strlenChar(azArg[i])>w ){
w = strlenChar(azArg[i]);
if( zVal && strlenChar(zVal)>w ){
w = strlenChar(zVal);
zSep = " ";
}
if( i==1 && p->aiIndent && p->pStmt ){
if( i==iIndent && p->aiIndent && p->pStmt ){
if( p->iIndent<p->nIndent ){
utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
}
p->iIndent++;
}
utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
fputs(i==nArg-1 ? "\n" : " ", p->out);
utf8_width_print(p->out, w, zVal ? zVal : p->nullValue);
fputs(i==nArg-1 ? "\n" : zSep, p->out);
}
break;
}
@@ -3292,17 +3353,11 @@ static int scanStatsHeight(sqlite3_stmt *p, int iEntry){
}
#endif
/*
** Display scan stats.
*/
static void display_scanstats(
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
static void display_explain_scanstats(
sqlite3 *db, /* Database to query */
ShellState *pArg /* Pointer to ShellState */
){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pArg);
#else
static const int f = SQLITE_SCANSTAT_COMPLEX;
sqlite3_stmt *p = pArg->pStmt;
int ii = 0;
@@ -3374,8 +3429,9 @@ static void display_scanstats(
}
eqp_render(pArg, nTotal);
#endif
}
#endif
/*
** Parameter azArray points to a zero-terminated array of strings. zStr
@@ -3413,8 +3469,6 @@ static int str_in_array(const char *zStr, const char **azArray){
** and "Goto" by 2 spaces.
*/
static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
const char *zSql; /* The text of the SQL statement */
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp; /* Index of operation in p->aiIndent[] */
@@ -3425,65 +3479,45 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
"Rewind", 0 };
const char *azGoto[] = { "Goto", 0 };
/* Try to figure out if this is really an EXPLAIN statement. If this
** cannot be verified, return early. */
if( sqlite3_column_count(pSql)!=8 ){
p->cMode = p->mode;
return;
}
zSql = sqlite3_sql(pSql);
if( zSql==0 ) return;
for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
if( sqlite3_strnicmp(z, "explain", 7) ){
p->cMode = p->mode;
return;
}
/* 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(pSql)>=4 );
assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 0), "addr" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 1), "opcode" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 2), "p1" ) );
assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 3), "p2" ) );
for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
int i;
int iAddr = sqlite3_column_int(pSql, 0);
const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
/* Set p2 to the P2 field of the current opcode. Then, 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 p1 = sqlite3_column_int(pSql, 2);
int p2 = sqlite3_column_int(pSql, 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));
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
if( iOp==0 ){
/* Do further verification that this is explain output. Abort if
** it is not */
static const char *explainCols[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
int jj;
for(jj=0; jj<ArraySize(explainCols); jj++){
if( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
p->cMode = p->mode;
sqlite3_reset(pSql);
return;
}
}
}
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
shell_check_oom(p->aiIndent);
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
shell_check_oom(abYield);
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) && p2op>0 ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
if( str_in_array(zOp, azGoto) && p2op<iOp && (abYield[p2op] || p1) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
}
@@ -3503,6 +3537,48 @@ static void explain_data_delete(ShellState *p){
p->iIndent = 0;
}
static void exec_prepared_stmt(ShellState*, sqlite3_stmt*);
/*
** Display scan stats.
*/
static void display_scanstats(
sqlite3 *db, /* Database to query */
ShellState *pArg /* Pointer to ShellState */
){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pArg);
#else
if( pArg->scanstatsOn==3 ){
const char *zSql =
" SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
" round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
" FROM bytecode(?)";
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_stmt *pSave = pArg->pStmt;
pArg->pStmt = pStmt;
sqlite3_bind_pointer(pStmt, 1, pSave, "stmt-pointer", 0);
pArg->cnt = 0;
pArg->cMode = MODE_ScanExp;
explain_data_prepare(pArg, pStmt);
exec_prepared_stmt(pArg, pStmt);
explain_data_delete(pArg);
sqlite3_finalize(pStmt);
pArg->pStmt = pSave;
}
}else{
display_explain_scanstats(db, pArg);
}
#endif
}
/*
** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
*/
@@ -4322,6 +4398,7 @@ static int shell_exec(
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc==SQLITE_OK ){
pArg->cMode = MODE_Explain;
assert( sqlite3_stmt_isexplain(pExplain)==1 );
explain_data_prepare(pArg, pExplain);
exec_prepared_stmt(pArg, pExplain);
explain_data_delete(pArg);
@@ -4340,9 +4417,10 @@ static int shell_exec(
}
if( pArg ){
int bIsExplain = (sqlite3_stmt_isexplain(pStmt)==1);
pArg->cMode = pArg->mode;
if( pArg->autoExplain ){
if( sqlite3_stmt_isexplain(pStmt)==1 ){
if( bIsExplain ){
pArg->cMode = MODE_Explain;
}
if( sqlite3_stmt_isexplain(pStmt)==2 ){
@@ -4352,7 +4430,7 @@ static int shell_exec(
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg->cMode==MODE_Explain ){
if( pArg->cMode==MODE_Explain && bIsExplain ){
explain_data_prepare(pArg, pStmt);
}
}
@@ -5463,6 +5541,12 @@ static void open_db(ShellState *p, int openFlags){
}
#endif
sqlite3_create_function(p->db, "strtod", 1, SQLITE_UTF8, 0,
shellStrtod, 0, 0);
sqlite3_create_function(p->db, "dtostr", 1, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
shellAddSchemaName, 0, 0);
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
@@ -9887,6 +9971,9 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
if( nArg==2 ){
if( cli_strcmp(azArg[1], "vm")==0 ){
p->scanstatsOn = 3;
}else
if( cli_strcmp(azArg[1], "est")==0 ){
p->scanstatsOn = 2;
}else{
@@ -10532,7 +10619,8 @@ static int do_meta_command(char *zLine, ShellState *p){
"with tabcols as materialized(\n"
"select tname, cname\n"
"from ("
" select ss.tname as tname, ti.name as cname\n"
" select printf('\"%%w\"',ss.tname) as tname,"
" printf('\"%%w\"',ti.name) as cname\n"
" from (%z) ss\n inner join pragma_table_info(tname) ti))\n"
"select 'SELECT total(bad_text_count) AS bad_text_count\n"
"FROM ('||group_concat(query, ' UNION ALL ')||')' as btc_query\n"
@@ -10804,7 +10892,7 @@ static int do_meta_command(char *zLine, ShellState *p){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
int unSafe; /* Not valid unless --unsafe-testing */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
@@ -10837,12 +10925,6 @@ static int do_meta_command(char *zLine, ShellState *p){
int i, n2;
const char *zCmd = 0;
if( !ShellHasFlag(p,SHFLG_TestingMode) ){
utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n",
"testctrl");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
zCmd = nArg>=2 ? azArg[1] : "help";
@@ -10856,6 +10938,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( cli_strcmp(zCmd,"help")==0 ){
utf8_printf(p->out, "Available test-controls:\n");
for(i=0; i<ArraySize(aCtrl); i++){
if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
utf8_printf(p->out, " .testctrl %s %s\n",
aCtrl[i].zCtrlName, aCtrl[i].zUsage);
}
@@ -10867,6 +10950,7 @@ static int do_meta_command(char *zLine, ShellState *p){
** of the option name, or a numerical value. */
n2 = strlen30(zCmd);
for(i=0; i<ArraySize(aCtrl); i++){
if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
@@ -10882,11 +10966,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
utf8_printf(stderr,
"line %d: \".testctrl %s\" may not be used in safe mode\n",
p->lineno, aCtrl[iCtrl].zCtrlName);
exit(1);
}else{
switch(testctrl){
+5
View File
@@ -1234,6 +1234,7 @@ typedef struct Cte Cte;
typedef struct CteUse CteUse;
typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct DblDbl DblDbl;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
@@ -1930,6 +1931,7 @@ struct FuncDestructor {
** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!!
@@ -1948,6 +1950,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
/* 0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
@@ -3891,6 +3894,7 @@ struct AuthContext {
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
@@ -5032,6 +5036,7 @@ int sqlite3FixSrcList(DbFixer*, SrcList*);
int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
i64 sqlite3RealToI64(double);
int sqlite3Int64ToText(i64,char*);
+44 -1
View File
@@ -2216,6 +2216,7 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
int flags = 0;
int iSelectId = 0;
int iParentId = 0;
int bDebug = 0;
if( objc==5 ){
struct Flag {
@@ -2223,6 +2224,7 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
int flag;
} aTbl[] = {
{"complex", SQLITE_SCANSTAT_COMPLEX},
{"debug", -1},
{0, 0}
};
@@ -2239,7 +2241,11 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal
);
if( res ) return TCL_ERROR;
flags |= aTbl[iVal].flag;
if( aTbl[iVal].flag==-1 ){
bDebug = 1;
}else{
flags |= aTbl[iVal].flag;
}
}
}
@@ -2253,6 +2259,13 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
return TCL_ERROR;
}
if( bDebug && 0==(flags & SQLITE_SCANSTAT_COMPLEX) ){
Tcl_SetObjResult(interp,
Tcl_NewStringObj("may not specify debug without complex", -1)
);
return TCL_ERROR;
}
if( idx<0 ){
Tcl_Obj *pRet = Tcl_NewObj();
res = sqlite3_stmt_scanstatus_v2(
@@ -2299,6 +2312,36 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
pStmt, idx, SQLITE_SCANSTAT_NCYCLE, flags, (void*)&nCycle);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nCycle", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nCycle));
if( bDebug ){
int ii;
ScanStatus *pScan = &((Vdbe*)pStmt)->aScan[idx];
Tcl_Obj *pRange = Tcl_NewObj();
Tcl_Obj *pCsr = Tcl_NewObj();
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("debug_loop", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(pScan->addrLoop));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("debug_visit", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(pScan->addrVisit));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("debug_explain",-1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(pScan->addrExplain));
for(ii=0; ii<ArraySize(pScan->aAddrRange)/2; ii++){
int iStart = pScan->aAddrRange[ii*2];
int iEnd = pScan->aAddrRange[ii*2+1];
if( iStart>0 ){
Tcl_ListObjAppendElement(0, pRange, Tcl_NewIntObj(iStart));
Tcl_ListObjAppendElement(0, pRange, Tcl_NewIntObj(iEnd));
}else if( iStart<0 ){
Tcl_ListObjAppendElement(0, pCsr, Tcl_NewIntObj(iEnd));
}
}
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("debug_range", -1));
Tcl_ListObjAppendElement(0, pRet, pRange);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("debug_csr", -1));
Tcl_ListObjAppendElement(0, pRet, pCsr);
}
Tcl_SetObjResult(interp, pRet);
}else{
Tcl_ResetResult(interp);
+4 -4
View File
@@ -468,7 +468,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
int esign = 1; /* sign of exponent */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
LONGDOUBLE_TYPE result;
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
@@ -597,7 +597,7 @@ do_atof_calc:
s = sign<0 ? -s : s;
if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
result = (double)s;
result = (LONGDOUBLE_TYPE)s;
}else{
/* attempt to handle extremely small/large numbers better */
if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
@@ -605,10 +605,10 @@ do_atof_calc:
LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
if( esign<0 ){
result = s / scale;
result /= 1.0e+308;
result /= 1.0e+308L;
}else{
result = s * scale;
result *= 1.0e+308;
result *= 1.0e+308L;
}
}else{ assert( e>=342 );
if( esign<0 ){
+9 -5
View File
@@ -3056,10 +3056,14 @@ op_column_restart:
pDest->flags = aFlag[t&1];
}
}else{
u8 p5;
pDest->enc = encoding;
/* This branch happens only when content is on overflow pages */
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
if( ((p5 = (pOp->p5 & OPFLAG_BYTELENARG))!=0
&& (p5==OPFLAG_TYPEOFARG
|| (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG))
)
)
|| (len = sqlite3VdbeSerialTypeLen(t))==0
){
/* Content is irrelevant for
@@ -5847,7 +5851,7 @@ case OP_SorterCompare: {
** parameter P3. Clearing the P3 column cache as part of this opcode saves
** us from having to issue a separate NullRow instruction to clear that cache.
*/
case OP_SorterData: {
case OP_SorterData: { /* ncycle */
VdbeCursor *pC;
pOut = &aMem[pOp->p2];
@@ -6122,8 +6126,8 @@ case OP_IfSmaller: { /* jump */
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
case OP_SorterSort: /* jump */
case OP_Sort: { /* jump */
case OP_SorterSort: /* jump ncycle */
case OP_Sort: { /* jump ncycle */
#ifdef SQLITE_TEST
sqlite3_sort_count++;
sqlite3_search_count--;
+3 -3
View File
@@ -538,7 +538,7 @@ int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
if( bPush){
pParse->addrExplain = iThis;
}
sqlite3VdbeScanStatus(v, iThis, 0, 0, 0, 0);
sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0);
}
return addr;
}
@@ -1250,8 +1250,8 @@ void sqlite3VdbeScanStatusCounters(
pScan = 0;
}
if( pScan ){
pScan->addrLoop = addrLoop;
pScan->addrVisit = addrVisit;
if( addrLoop>0 ) pScan->addrLoop = addrLoop;
if( addrVisit>0 ) pScan->addrVisit = addrVisit;
}
}
}
+2 -32
View File
@@ -575,36 +575,6 @@ void sqlite3VdbeMemReleaseMalloc(Mem *p){
if( p->szMalloc ) vdbeMemClear(p);
}
/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
*/
static SQLITE_NOINLINE i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
#else
/*
** Many compilers we encounter do not define constants for the
** minimum and maximum 64-bit integers, or they define them
** inconsistently. And many do not understand the "LL" notation.
** So we define our own static constants here using nothing
** larger than a 32-bit integer constant.
*/
static const i64 maxInt = LARGEST_INT64;
static const i64 minInt = SMALLEST_INT64;
if( r<=(double)minInt ){
return minInt;
}else if( r>=(double)maxInt ){
return maxInt;
}else{
return (i64)r;
}
#endif
}
/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
@@ -631,7 +601,7 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){
testcase( flags & MEM_IntReal );
return pMem->u.i;
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
return sqlite3RealToI64(pMem->u.r);
}else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
return memIntValue(pMem);
}else{
@@ -693,7 +663,7 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
if( pMem->flags & MEM_IntReal ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
i64 ix = doubleToInt64(pMem->u.r);
i64 ix = sqlite3RealToI64(pMem->u.r);
/* Only mark the value as an integer if
**
+23 -6
View File
@@ -69,6 +69,8 @@ static int bytecodevtabConnect(
"p5 INT,"
"comment TEXT,"
"subprog TEXT,"
"nexec INT,"
"ncycle INT,"
"stmt HIDDEN"
");",
@@ -231,7 +233,7 @@ static int bytecodevtabColumn(
}
}
}
i += 10;
i += 20;
}
}
switch( i ){
@@ -281,16 +283,31 @@ static int bytecodevtabColumn(
}
break;
}
case 10: /* tables_used.type */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
case 9: /* nexec */
sqlite3_result_int(ctx, pOp->nExec);
break;
case 10: /* ncycle */
sqlite3_result_int(ctx, pOp->nCycle);
break;
#else
case 9: /* nexec */
case 10: /* ncycle */
sqlite3_result_int(ctx, 0);
break;
#endif
case 20: /* tables_used.type */
sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
break;
case 11: /* tables_used.schema */
case 21: /* tables_used.schema */
sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
break;
case 12: /* tables_used.name */
case 22: /* tables_used.name */
sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
break;
case 13: /* tables_used.wr */
case 23: /* tables_used.wr */
sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
break;
}
@@ -364,7 +381,7 @@ static int bytecodevtabBestIndex(
int rc = SQLITE_CONSTRAINT;
struct sqlite3_index_constraint *p;
bytecodevtab *pVTab = (bytecodevtab*)tab;
int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
int iBaseCol = pVTab->bTablesUsed ? 4 : 10;
pIdxInfo->estimatedCost = (double)100;
pIdxInfo->estimatedRows = 100;
pIdxInfo->idxNum = 0;
+6
View File
@@ -315,6 +315,12 @@ void sqlite3WhereAddScanStatus(
if( wsFlags & WHERE_INDEXED ){
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
}
}else{
int addr = pSrclist->a[pLvl->iFrom].addrFillSub;
VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1);
}
}
}
+16 -9
View File
@@ -23,31 +23,34 @@ do_execsql_test 1000 {
SELECT decimal(1);
} {1}
do_execsql_test 1010 {
SELECT decimal(1.0);
SELECT decimal('1.0');
} {1.0}
do_execsql_test 1020 {
SELECT decimal(0001.0);
SELECT decimal('0001.0');
} {1.0}
do_execsql_test 1030 {
SELECT decimal(+0001.0);
SELECT decimal('+0001.0');
} {1.0}
do_execsql_test 1040 {
SELECT decimal(-0001.0);
SELECT decimal('-0001.0');
} {-1.0}
do_execsql_test 1050 {
SELECT decimal(1.0e72);
SELECT decimal('1.0e72');
} {1000000000000000000000000000000000000000000000000000000000000000000000000}
# 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123
do_execsql_test 1060 {
SELECT decimal(1.0e-72);
SELECT decimal('1.0e-72');
} {0.0000000000000000000000000000000000000000000000000000000000000000000000010}
# 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123
do_execsql_test 1070 {
SELECT decimal(-123e-4);
SELECT decimal('-123e-4');
} {-0.0123}
do_execsql_test 1080 {
SELECT decimal(+123e+4);
} {1230000.0}
SELECT decimal('+123e+4');
} {1230000}
do_execsql_test 1081 {
SELECT decimal_sci('+123e+4');
} {+1.23e+06}
do_execsql_test 2000 {
@@ -161,6 +164,10 @@ do_execsql_test 6010 {
SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
} {0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625}
do_execsql_test 6011 {
WITH c(n) AS (SELECT ieee754_from_blob(x'0000000000000001'))
SELECT decimal(c.n) FROM c;
} {0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625}
do_execsql_test 6020 {
WITH c(n) AS (SELECT ieee754_from_blob(x'7fefffffffffffff'))
SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
+46 -24
View File
@@ -42,6 +42,9 @@ do_test func-0.1 {
do_test func-1.0 {
execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
} {4 2 7 8 4}
do_execsql_test func-1.0b {
SELECT octet_length(t1) FROM tbl1 ORDER BY t1;
} {4 2 7 8 4}
do_test func-1.1 {
set r [catch {execsql {SELECT length(*) FROM tbl1 ORDER BY t1}} msg]
lappend r $msg
@@ -57,9 +60,29 @@ do_test func-1.3 {
do_test func-1.4 {
execsql {SELECT coalesce(length(a),-1) FROM t2}
} {1 -1 3 -1 5}
do_execsql_test func-1.5 {
SELECT octet_length(12345);
} {5}
db null NULL
do_execsql_test func-1.6 {
SELECT octet_length(NULL);
} {NULL}
do_execsql_test func-1.7 {
SELECT octet_length(7.5);
} {3}
do_execsql_test func-1.8 {
SELECT octet_length(x'30313233');
} {4}
do_execsql_test func-1.9 {
WITH c(x) AS (VALUES(char(350,351,352,353,354)))
SELECT length(x), octet_length(x) FROM c;
} {5 10}
# Check out the substr() function
#
db null {}
do_test func-2.0 {
execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
} {fr is pr so th}
@@ -839,30 +862,13 @@ do_test func-18.11 {
}
} integer
ifcapable floatingpoint {
do_test func-18.12 {
catchsql {
INSERT INTO t6 VALUES(1<<62);
SELECT sum(x) - ((1<<62)*2.0+1) from t6;
}
do_catchsql_test func-18.12 {
INSERT INTO t6 VALUES(1<<62);
SELECT sum(x) - ((1<<62)*2.0+1) from t6;
} {1 {integer overflow}}
do_test func-18.13 {
execsql {
SELECT total(x) - ((1<<62)*2.0+1) FROM t6
}
} 0.0
}
ifcapable !floatingpoint {
do_test func-18.12 {
catchsql {
INSERT INTO t6 VALUES(1<<62);
SELECT sum(x) - ((1<<62)*2+1) from t6;
}
} {1 {integer overflow}}
do_test func-18.13 {
execsql {
SELECT total(x) - ((1<<62)*2+1) FROM t6
}
} 0.0
do_catchsql_test func-18.13 {
SELECT total(x) - ((1<<62)*2.0+1) FROM t6
} {0 0.0}
}
if {[working_64bit_int]} {
do_test func-18.14 {
@@ -1520,6 +1526,22 @@ do_execsql_test func-36.110 {
SELECT 123 ->> 456
} {123->>456}
# 2023-06-26
# Enhanced precision of SUM().
#
reset_db
do_catchsql_test func-37.100 {
WITH c(x) AS (VALUES(9223372036854775807),(9223372036854775807),
(123),(-9223372036854775807),(-9223372036854775807))
SELECT sum(x) FROM c;
} {1 {integer overflow}}
do_catchsql_test func-37.110 {
WITH c(x) AS (VALUES(9223372036854775807),(1))
SELECT sum(x) FROM c;
} {1 {integer overflow}}
do_catchsql_test func-37.120 {
WITH c(x) AS (VALUES(9223372036854775807),(10000),(-10010))
SELECT sum(x) FROM c;
} {1 {integer overflow}}
finish_test
+65 -4
View File
@@ -55,11 +55,12 @@ proc get_cycles {stmt} {
dict get $r nCycle
}
proc foreach_scan {varname stmt body} {
proc foreach_scan {varname stmt body {debug 0}} {
upvar $varname var
for {set ii 0} {1} {incr ii} {
set r [sqlite3_stmt_scanstatus -flags complex $stmt $ii]
set f "complex"
if {$debug} { set f "complex debug" }
set r [sqlite3_stmt_scanstatus -flags $f $stmt $ii]
if {[llength $r]==0} break
array set var $r
uplevel $body
@@ -102,6 +103,15 @@ proc puts_graph {sql} {
puts [string trim [get_graph $stmt]]
}
proc puts_debug_info {sql} {
db eval $sql
set stmt [db version -last-stmt-ptr]
foreach_scan X $stmt {
puts -nonewline "$X(debug_explain) $X(zExplain): "
puts -nonewline "loop=$X(debug_loop) visit=$X(debug_visit) "
puts "csr=$X(debug_csr) range=$X(debug_range)"
} 1
}
do_zexplain_test 0 1.1 {
SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
@@ -235,7 +245,7 @@ do_graph_test 4.5 {
QUERY (nCycle=nnn)
--CO-ROUTINE v1
----SCAN rt2 (nCycle=nnn)
----USE TEMP B-TREE FOR GROUP BY
----USE TEMP B-TREE FOR GROUP BY (nCycle=nnn)
--SCAN rt1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON v1(x1, cnt) (nCycle=nnn)
--BLOOM FILTER ON v1 (x1=?)
@@ -270,6 +280,57 @@ ifcapable trace {
} {{SCAN t1} {SCAN t1} {SCAN t1}}
}
#-------------------------------------------------------------------------
reset_db
sqlite3_db_config db STMT_SCANSTATUS 1
do_execsql_test 6.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
INSERT INTO t1 VALUES(5, 'five');
INSERT INTO t1 VALUES(6, 'six');
INSERT INTO t1 VALUES(7, 'seven');
INSERT INTO t1 VALUES(8, 'eight');
}
do_graph_test 6.1 {
SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1
} {
QUERY (nCycle=nnn)
--SCAN t1 (nCycle=nnn)
--USE TEMP B-TREE FOR GROUP BY (nCycle=nnn)
}
set sql {
WITH xy(x, y) AS ( SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1)
SELECT * FROM xy WHERE x=1
}
do_graph_test 6.2 $sql {
QUERY (nCycle=nnn)
--CO-ROUTINE xy
----SCAN t1 (nCycle=nnn)
----USE TEMP B-TREE FOR GROUP BY (nCycle=nnn)
--SCAN xy (nCycle=nnn)
}
do_graph_test 6.3 {
WITH xy(x, y) AS ( SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1)
SELECT * FROM xy, xy AS xy2
} {
QUERY (nCycle=nnn)
--MATERIALIZE xy (nCycle=nnn)
----SCAN t1 (nCycle=nnn)
----USE TEMP B-TREE FOR GROUP BY (nCycle=nnn)
--SCAN xy (nCycle=nnn)
--SCAN xy2 (nCycle=nnn)
}
#explain_i { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 }
#puts_debug_info { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 }
finish_test
+9
View File
@@ -262,5 +262,14 @@ do_test shell2-1.4.11 {
SELECT count(*) FROM t;}]]
} {0 1}
# Bug from forum post 7cbe081746dd3803
# Keywords as column names were producing an error message.
do_test shell2-1.4.12 {
set res [catchcmd :memory: [string trim {
CREATE TABLE "group"("order" text);
INSERT INTO "group" VALUES ('ABC');
.sha3sum}]]
} {0 ca08bc02b7e95c7df431a3a4b1cc0f8d8743914793473f55b5558e03}
finish_test