Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 676f17a570 | |||
| afef7fc136 | |||
| bae91082dd | |||
| 7d0103bb06 | |||
| 68c88ea04f | |||
| 3e1e7aad3d | |||
| 59f13119cf | |||
| 26cd8bc1af | |||
| 45d7562843 | |||
| 3748b7329f | |||
| efd0cf87df | |||
| 728650ecb3 | |||
| e68899f1e4 | |||
| 85ca6d7ace | |||
| 1790ccb98b | |||
| 6aa5a42beb | |||
| 7623795018 | |||
| aa4356da68 | |||
| 930e4167bd | |||
| 521f20e3d3 | |||
| c9f240cea4 | |||
| 1b3c6e727e | |||
| 0478d1d88a | |||
| b884158434 | |||
| 841e596ad0 | |||
| bc2b65832e | |||
| 5270d7424d | |||
| 37b188fbca | |||
| c8885d42fe | |||
| c27bda0b79 | |||
| fecdff4354 | |||
| 453be55b85 | |||
| 17c20bb15e | |||
| 9ee9444a0a | |||
| 42d042e602 | |||
| 3f073f9ef8 | |||
| aebeabacff | |||
| 002330dc48 | |||
| a1b0ff1735 | |||
| 24b368da8d | |||
| 4cd3a59a79 | |||
| 07d76f7b95 | |||
| 1bfe92a691 | |||
| 48114d08cf | |||
| dd8b12a6c5 | |||
| 60f41362cf | |||
| 2ddfa6a360 | |||
| ec3e57fa92 | |||
| 500ca334bd | |||
| 0b1a1e8c37 | |||
| a75011a891 | |||
| cd88a74115 | |||
| 9ea7632cca | |||
| 7f5fe1faf3 | |||
| 8fbb335d9f | |||
| 60783f47b2 | |||
| d847c73153 | |||
| 12b198f1a2 | |||
| 502c618f01 | |||
| b9561384d0 | |||
| d2b9cdd592 | |||
| cc19bed8b1 | |||
| 077efc2730 | |||
| 7f9dcd664d | |||
| d6c671e626 | |||
| d4170ac0eb | |||
| 71aac8763f | |||
| b3d7f1c2db |
@@ -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
@@ -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,
|
||||
|
||||
+32
-1
@@ -256,6 +256,37 @@ static void ieee754func_to_blob(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL Function: ieee754_inc(r,N)
|
||||
**
|
||||
** Move the floating point value r by N quantums and return the new
|
||||
** values.
|
||||
**
|
||||
** Behind the scenes: this routine merely casts r into a 64-bit unsigned
|
||||
** integer, adds N, then casts the value back into float.
|
||||
**
|
||||
** Example: To find the smallest positive number:
|
||||
**
|
||||
** SELECT ieee754_inc(0.0,+1);
|
||||
*/
|
||||
static void ieee754inc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
double r;
|
||||
sqlite3_int64 N;
|
||||
sqlite3_uint64 m1, m2;
|
||||
double r2;
|
||||
UNUSED_PARAMETER(argc);
|
||||
r = sqlite3_value_double(argv[0]);
|
||||
N = sqlite3_value_int64(argv[1]);
|
||||
memcpy(&m1, &r, 8);
|
||||
m2 = m1 + N;
|
||||
memcpy(&r2, &m2, 8);
|
||||
sqlite3_result_double(context, r2);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
@@ -277,7 +308,7 @@ int sqlite3_ieee_init(
|
||||
{ "ieee754_exponent", 1, 2, ieee754func },
|
||||
{ "ieee754_to_blob", 1, 0, ieee754func_to_blob },
|
||||
{ "ieee754_from_blob", 1, 0, ieee754func_from_blob },
|
||||
|
||||
{ "ieee754_inc", 2, 0, ieee754inc },
|
||||
};
|
||||
unsigned int i;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Add\sthe\s--pcachetrace\soption\sto\sthe\sCLI.
|
||||
D 2023-06-21T14:11:25.888
|
||||
C Proof\sof\sconcept\sfor\sa\snew\ssqlite3_function_needed()\sinterface.
|
||||
D 2023-07-07T16:58:20.565
|
||||
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,13 +287,13 @@ 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
|
||||
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
|
||||
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
|
||||
F ext/misc/ieee754.c 984d51fe23e956484ec1049df6f5257002e3ab338cabceb39761c2e80ad10bf4
|
||||
F ext/misc/ieee754.c 62a90978204d2c956d5036eb89e548e736ca5fac0e965912867ddd7bb833256d
|
||||
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
|
||||
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
|
||||
F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
|
||||
@@ -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,22 +576,22 @@ 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
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/callback.c 3520e686ab1d427f33cffb46d554d0a0a2a588866a195c69d1a17103b67dde18
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
|
||||
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/global.c bd0892ade7289f6e20bff44c07d06371f2ff9b53cea359e7854b9b72f65adc30
|
||||
F src/func.c b2325dc2fb0b43874fa5f2ae4e83262bdda952fc317b294dfca5ce70d5049bcd
|
||||
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
@@ -600,7 +600,7 @@ F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||
F src/json.c 14c474fb1249a46eb44e878e2361f36abfe686b134039b0d1883d93d61505b4a
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
|
||||
F src/main.c 5fd4b65d61ae6155f36756ed508a39b38b49355b031188961e8d923f43f4bc49
|
||||
F src/main.c d869b4032a2717b24ad0fd82266ea4d79304a25d942a4b332ff307009f6f10e3
|
||||
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -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 84b7b4b647f336934a5ab2e7f0c52555833cc0778d2d60e016cca52ee8c6cd8f
|
||||
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/sqlite.h.in 3076d78836b6dac53b3ab0875fc8fd15bca8077aad4d33c85336e05af6aef8c7
|
||||
F src/select.c 3ab1186290a311a8ceed1286c0e286209f7fe97b2d02c7593258004ce295dd88
|
||||
F src/shell.c.in d6c9ac6ab2c56eac0009ad383f6fd31a410d4cfa04ddf5875496207773fc60b1
|
||||
F src/sqlite.h.in 287bce997bc287c251558b41ffb4ec025b98e7d0c74e3bf22c4919d2edb6d44c
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
|
||||
F src/sqliteInt.h 8974b60740b108269f51e833e85191be6bf9f06f317ee34a53b7ec215762cf8c
|
||||
F src/sqlite3ext.h 51ee0eff1f843bd233c3441d220812964d2166f3c5e5714e7a3d847a778310c4
|
||||
F src/sqliteInt.h 3323b237e3f951a4e0297ce797fb7e65bade820f04aa90876a3cf7c1eee029eb
|
||||
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 9111b12427b3b94429aff68bbcf5b125ae70438f6ce2f3f033e2a69626ec26c9
|
||||
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
|
||||
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
|
||||
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
|
||||
@@ -705,15 +705,15 @@ 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 eac357cf07fd9be14e467e9f38e9888acf2bec8d6221903c5e57136725170880
|
||||
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 cf4a1556dd5b18c071cf7c243373c29ce752eb516022e3ad49ba72f08b785033
|
||||
F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
|
||||
@@ -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
|
||||
@@ -775,7 +775,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test 1f24a6f16e44892848298bd8e488159d4a60cf47be003d32747a136103c9bbac
|
||||
F test/atof1.test f2765d7fdc1348ae58b279d096d301a208e46da623213877b2ba580dc2768975
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
|
||||
@@ -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
|
||||
@@ -1014,6 +1014,8 @@ F test/fkey8.test 51deda7f1a1448bca95875e4a6e1a3a75b4bd7215e924e845bd60de60e4d84
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958fdde5c
|
||||
F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
|
||||
F test/fp-speed-1.c ca95152d579530c967240ead1387dc1208052d310dfa22bc9ebded56d4e6c026
|
||||
F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
|
||||
@@ -1107,7 +1109,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 2acd982669b2c15ceccc046385b458e985f90c9ca58b14d0ef75eec79c32f45b
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
|
||||
@@ -1391,7 +1393,7 @@ F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0
|
||||
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
|
||||
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
|
||||
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
|
||||
F test/releasetest_data.tcl b550dd1b122a9c969df794d05ea272df535f10ff1a245062e7ba080822378016
|
||||
F test/releasetest_data.tcl c8cf85aeb313a771e18dae01396f5ca70e85d4574df681990629b1103f185afe
|
||||
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test db532cde29d6aebbc48c6ddc3149b30476f8e69ca7a2c4b53986c7635e6fd8ec
|
||||
@@ -1399,7 +1401,7 @@ F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb076793
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
F test/round1.test 1bb32cf3fc505eed9e86b5e523d07e15d4428189665524587512fbcc85d114bb
|
||||
F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190cfd4
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test e29025be95baf6b32f0d5edef59a7633028325896a98f1caa8019559ca910350
|
||||
@@ -1425,7 +1427,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 +1471,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
|
||||
@@ -1509,7 +1511,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c 9703465daf778dd90bad7adadc1d2ee205ec90a79437cababab0a4111190f0c8
|
||||
F test/speedtest1.c f9505ad6f9c2c3c488a370a2d193e9603a030e51126ef3ecfeb056d21f0e7ad5
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1996,7 +1998,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
|
||||
F tool/showwal.c 65ecabae3a2dcff4116301d5a8dbb8c4964814da1b2aff6d85c806a88b71fa4e
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 1b5be34c6223cb1af06da2a10fb77863eb869b1962d055820b0a11cf2336ab45
|
||||
F tool/speed-check.sh c24c30cddd0ecb6d1d0775411d22f7619f55fa696a305487645e27b1b8fc05a2
|
||||
F tool/speed-check.sh 72dc85b2c0484af971ee3e7d10775f72b4e771e27e162c2099b3bf25517c25fb
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
@@ -2041,8 +2043,11 @@ 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
|
||||
P d3532eaed1cc671d8149b1bd34ead2a88fb83502a2898a5f60aea0a7daf18958
|
||||
R d4ed9da3aa6365c836a379cf03c29a8d
|
||||
T *branch * need-function
|
||||
T *sym-need-function *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 6142bb2a618d1d23b62eb525e555db78
|
||||
Z e80e56952de95f04df4da782eb785cf5
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1
|
||||
cd67edc032983b5111ffcf6c73ca1308ef67cf2f16baa25788121827b3038d2f
|
||||
+59
-50
@@ -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))
|
||||
|
||||
@@ -474,7 +474,28 @@ FuncDef *sqlite3FindFunction(
|
||||
|
||||
if( pBest && (pBest->xSFunc || createFlag) ){
|
||||
return pBest;
|
||||
}else if( db->xFuncNeeded!=0 ){
|
||||
int rc;
|
||||
int (*xFN)(void*,sqlite3*,const char*,int,int) = db->xFuncNeeded;
|
||||
db->xFuncNeeded = 0;
|
||||
rc = xFN(db->pFuncNeededArg,db,zName,nArg,enc);
|
||||
db->xFuncNeeded = xFN;
|
||||
pBest = 0;
|
||||
bestScore = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
p = (FuncDef*)sqlite3HashFind(&db->aFunc,zName);
|
||||
while( p ){
|
||||
int score = matchQuality(p, nArg, enc);
|
||||
if( score>bestScore ){
|
||||
pBest = p;
|
||||
bestScore = score;
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
return pBest;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+185
-24
@@ -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.
|
||||
**
|
||||
@@ -425,7 +461,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
}else if( n==0 ){
|
||||
r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
|
||||
}else{
|
||||
zBuf = sqlite3_mprintf("%.*f",n,r);
|
||||
zBuf = sqlite3_mprintf("%!.*f",n,r);
|
||||
if( zBuf==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
@@ -1634,13 +1670,68 @@ 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 */
|
||||
double rErr; /* Error term for Kahan-Babushka-Neumaier summation */
|
||||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
** Do one step of the Kahan-Babushka-Neumaier summation.
|
||||
**
|
||||
** https://en.wikipedia.org/wiki/Kahan_summation_algorithm
|
||||
**
|
||||
** Variables are marked "volatile" to defeat c89 x86 floating point
|
||||
** optimizations can mess up this algorithm.
|
||||
*/
|
||||
static void kahanBabuskaNeumaierStep(
|
||||
volatile SumCtx *pSum,
|
||||
volatile double r
|
||||
){
|
||||
volatile double s = pSum->rSum;
|
||||
volatile double t = s + r;
|
||||
if( fabs(s) > fabs(r) ){
|
||||
pSum->rErr += (s - t) + r;
|
||||
}else{
|
||||
pSum->rErr += (r - t) + s;
|
||||
}
|
||||
pSum->rSum = t;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a (possibly large) integer to the running sum.
|
||||
*/
|
||||
static void kahanBabuskaNeumaierStepInt64(volatile SumCtx *pSum, i64 iVal){
|
||||
if( iVal<=-4503599627370496 || iVal>=+4503599627370496 ){
|
||||
i64 iBig, iSm;
|
||||
iSm = iVal % 16384;
|
||||
iBig = iVal - iSm;
|
||||
kahanBabuskaNeumaierStep(pSum, iBig);
|
||||
kahanBabuskaNeumaierStep(pSum, iSm);
|
||||
}else{
|
||||
kahanBabuskaNeumaierStep(pSum, (double)iVal);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize the Kahan-Babaska-Neumaier sum from a 64-bit integer
|
||||
*/
|
||||
static void kahanBabuskaNeumaierInit(
|
||||
volatile SumCtx *p,
|
||||
i64 iVal
|
||||
){
|
||||
if( iVal<=-4503599627370496 || iVal>=+4503599627370496 ){
|
||||
i64 iSm = iVal % 16384;
|
||||
p->rSum = (double)(iVal - iSm);
|
||||
p->rErr = (double)iSm;
|
||||
}else{
|
||||
p->rSum = (double)iVal;
|
||||
p->rErr = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Routines used to compute the sum, average, and total.
|
||||
**
|
||||
@@ -1660,15 +1751,30 @@ 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 ){
|
||||
kahanBabuskaNeumaierInit(p, p->iSum);
|
||||
p->approx = 1;
|
||||
kahanBabuskaNeumaierStep(p, 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;
|
||||
kahanBabuskaNeumaierInit(p, p->iSum);
|
||||
p->approx = 1;
|
||||
kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0]));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
p->rSum += sqlite3_value_double(argv[0]);
|
||||
p->approx = 1;
|
||||
if( type==SQLITE_INTEGER ){
|
||||
kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0]));
|
||||
}else{
|
||||
p->ovrfl = 0;
|
||||
kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1685,13 +1791,18 @@ 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;
|
||||
if( !p->approx ){
|
||||
p->iSum -= sqlite3_value_int64(argv[0]);
|
||||
}else if( type==SQLITE_INTEGER ){
|
||||
i64 iVal = sqlite3_value_int64(argv[0]);
|
||||
if( iVal!=SMALLEST_INT64 ){
|
||||
kahanBabuskaNeumaierStepInt64(p, -iVal);
|
||||
}else{
|
||||
kahanBabuskaNeumaierStepInt64(p, LARGEST_INT64);
|
||||
kahanBabuskaNeumaierStepInt64(p, 1);
|
||||
}
|
||||
}else{
|
||||
p->rSum -= sqlite3_value_double(argv[0]);
|
||||
kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1702,10 +1813,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+p->rErr);
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_int64(context, p->iSum);
|
||||
}
|
||||
@@ -1715,14 +1828,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+p->rErr;
|
||||
}else{
|
||||
r = (double)(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+p->rErr;
|
||||
}else{
|
||||
r = (double)(p->iSum);
|
||||
}
|
||||
}
|
||||
sqlite3_result_double(context, r);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2312,6 +2438,37 @@ static void signFunc(
|
||||
sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Implementation of fpdecode(x,y,z) function.
|
||||
**
|
||||
** x is a real number that is to be decoded. y is the precision.
|
||||
** z is the maximum real precision.
|
||||
*/
|
||||
static void fpdecodeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
FpDecode s;
|
||||
double x;
|
||||
int y, z;
|
||||
char zBuf[100];
|
||||
UNUSED_PARAMETER(argc);
|
||||
assert( argc==3 );
|
||||
x = sqlite3_value_double(argv[0]);
|
||||
y = sqlite3_value_int(argv[1]);
|
||||
z = sqlite3_value_int(argv[2]);
|
||||
sqlite3FpDecode(&s, x, y, z);
|
||||
if( s.isSpecial==2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP);
|
||||
}
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** All of the FuncDef structures in the aBuiltinFunc[] array above
|
||||
** to the global function hash table. This occurs at start-time (as
|
||||
@@ -2376,12 +2533,16 @@ 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 ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
#ifdef SQLITE_DEBUG
|
||||
FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ),
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
FUNCTION(round, 1, 0, 0, roundFunc ),
|
||||
FUNCTION(round, 2, 0, 0, roundFunc ),
|
||||
|
||||
@@ -243,6 +243,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
|
||||
0, /* bSmallMalloc */
|
||||
1, /* bExtraSchemaChecks */
|
||||
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
|
||||
0x7ffffffe, /* mxStrlen */
|
||||
0, /* neverCorrupt */
|
||||
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
|
||||
|
||||
+40
@@ -1219,6 +1219,9 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
|
||||
db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
|
||||
}
|
||||
|
||||
/* Free the function-needed payload pointer */
|
||||
if( db->xFuncNeededFree ) db->xFuncNeededFree(db->pFuncNeededArg);
|
||||
|
||||
/* Force xDisconnect calls on all virtual tables */
|
||||
disconnectAllVtab(db);
|
||||
|
||||
@@ -3705,6 +3708,28 @@ int sqlite3_collation_needed16(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_UTF16 */
|
||||
|
||||
/*
|
||||
** Register a collation sequence factory callback with the database handle
|
||||
** db. Replace any previously installed collation sequence factory.
|
||||
*/
|
||||
int sqlite3_function_needed(
|
||||
sqlite3 *db,
|
||||
void *pFuncNeededArg,
|
||||
int (*xFuncNeeded)(void*,sqlite3*,const char*,int,int),
|
||||
void (*xFuncNeededFree)(void*)
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( db->xFuncNeededFree ) db->xFuncNeededFree(db->pFuncNeededArg);
|
||||
db->pFuncNeededArg = pFuncNeededArg;
|
||||
db->xFuncNeeded = xFuncNeeded;
|
||||
db->xFuncNeededFree = xFuncNeededFree;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
/*
|
||||
** This function is now an anachronism. It used to be used to recover from a
|
||||
@@ -4470,6 +4495,21 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X);
|
||||
**
|
||||
** X<0 Make no changes to the bUseLongDouble. Just report value.
|
||||
** X==0 Disable bUseLongDouble
|
||||
** X==1 Enable bUseLongDouble
|
||||
** X==2 Set bUseLongDouble to its default value for this platform
|
||||
*/
|
||||
case SQLITE_TESTCTRL_USELONGDOUBLE: {
|
||||
int b = va_arg(ap, int);
|
||||
if( b==2 ) b = sizeof(LONGDOUBLE_TYPE)>8;
|
||||
if( b>=0 ) sqlite3Config.bUseLongDouble = b>0;
|
||||
rc = sqlite3Config.bUseLongDouble!=0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
|
||||
|
||||
+50
-150
@@ -105,57 +105,6 @@ static const et_info fmtinfo[] = {
|
||||
** %!S Like %S but prefer the zName over the zAlias
|
||||
*/
|
||||
|
||||
/* Floating point constants used for rounding */
|
||||
static const double arRound[] = {
|
||||
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
|
||||
5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
|
||||
};
|
||||
|
||||
/*
|
||||
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
|
||||
** conversions will work.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** "*val" is a double such that 0.1 <= *val < 10.0
|
||||
** Return the ascii code for the leading digit of *val, then
|
||||
** multiply "*val" by 10.0 to renormalize.
|
||||
**
|
||||
** Example:
|
||||
** input: *val = 3.14159
|
||||
** output: *val = 1.4159 function return = '3'
|
||||
**
|
||||
** The counter *cnt is incremented each time. After counter exceeds
|
||||
** 16 (the number of significant digits in a 64-bit float) '0' is
|
||||
** always returned.
|
||||
*/
|
||||
static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
|
||||
int digit;
|
||||
LONGDOUBLE_TYPE d;
|
||||
if( (*cnt)<=0 ) return '0';
|
||||
(*cnt)--;
|
||||
digit = (int)*val;
|
||||
d = digit;
|
||||
digit += '0';
|
||||
*val = (*val - d)*10.0;
|
||||
return (char)digit;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** "*val" is a u64. *msd is a divisor used to extract the
|
||||
** most significant digit of *val. Extract that most significant
|
||||
** digit and return it.
|
||||
*/
|
||||
static char et_getdigit_int(u64 *val, u64 *msd){
|
||||
u64 x = (*val)/(*msd);
|
||||
*val -= x*(*msd);
|
||||
if( *msd>=10 ) *msd /= 10;
|
||||
return '0' + (char)(x & 15);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
/*
|
||||
** Set the StrAccum object to an error mode.
|
||||
*/
|
||||
@@ -247,20 +196,15 @@ void sqlite3_str_vappendf(
|
||||
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
|
||||
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
|
||||
sqlite_uint64 longvalue; /* Value for integer types */
|
||||
LONGDOUBLE_TYPE realvalue; /* Value for real types */
|
||||
sqlite_uint64 msd; /* Divisor to get most-significant-digit
|
||||
** of longvalue */
|
||||
double realvalue; /* Value for real types */
|
||||
const et_info *infop; /* Pointer to the appropriate info structure */
|
||||
char *zOut; /* Rendering buffer */
|
||||
int nOut; /* Size of the rendering buffer */
|
||||
char *zExtra = 0; /* Malloced memory used by some conversion */
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int exp, e2; /* exponent of real numbers */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
double rounder; /* Used for rounding floating point values */
|
||||
int exp, e2; /* exponent of real numbers */
|
||||
etByte flag_dp; /* True if decimal point should be shown */
|
||||
etByte flag_rtz; /* True if trailing zeros should be removed */
|
||||
#endif
|
||||
|
||||
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
|
||||
@@ -535,94 +479,61 @@ void sqlite3_str_vappendf(
|
||||
break;
|
||||
case etFLOAT:
|
||||
case etEXP:
|
||||
case etGENERIC:
|
||||
case etGENERIC: {
|
||||
FpDecode s;
|
||||
int iRound;
|
||||
int j;
|
||||
|
||||
if( bArgList ){
|
||||
realvalue = getDoubleArg(pArgList);
|
||||
}else{
|
||||
realvalue = va_arg(ap,double);
|
||||
}
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
length = 0;
|
||||
#else
|
||||
if( precision<0 ) precision = 6; /* Set default precision */
|
||||
#ifdef SQLITE_FP_PRECISION_LIMIT
|
||||
if( precision>SQLITE_FP_PRECISION_LIMIT ){
|
||||
precision = SQLITE_FP_PRECISION_LIMIT;
|
||||
}
|
||||
#endif
|
||||
if( realvalue<0.0 ){
|
||||
realvalue = -realvalue;
|
||||
if( xtype==etFLOAT ){
|
||||
iRound = -precision;
|
||||
}else if( xtype==etGENERIC ){
|
||||
iRound = precision;
|
||||
}else{
|
||||
iRound = precision+1;
|
||||
}
|
||||
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
|
||||
if( s.isSpecial ){
|
||||
if( s.isSpecial==2 ){
|
||||
bufpt = flag_zeropad ? "null" : "NaN";
|
||||
length = sqlite3Strlen30(bufpt);
|
||||
break;
|
||||
}else if( flag_zeropad ){
|
||||
s.z[0] = '9';
|
||||
s.iDP = 1000;
|
||||
s.n = 1;
|
||||
}else{
|
||||
memcpy(buf, "-Inf", 5);
|
||||
bufpt = buf;
|
||||
if( s.sign=='-' ){
|
||||
/* no-op */
|
||||
}else if( flag_prefix ){
|
||||
buf[0] = flag_prefix;
|
||||
}else{
|
||||
bufpt++;
|
||||
}
|
||||
length = sqlite3Strlen30(bufpt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( s.sign=='-' ){
|
||||
prefix = '-';
|
||||
}else{
|
||||
prefix = flag_prefix;
|
||||
}
|
||||
exp = 0;
|
||||
if( xtype==etGENERIC && precision>0 ) precision--;
|
||||
testcase( precision>0xfff );
|
||||
if( realvalue<1.0e+16
|
||||
&& realvalue==(LONGDOUBLE_TYPE)(longvalue = (u64)realvalue)
|
||||
){
|
||||
/* Number is a pure integer that can be represented as u64 */
|
||||
for(msd=1; msd*10<=longvalue; msd *= 10, exp++){}
|
||||
if( exp>precision && xtype!=etFLOAT ){
|
||||
u64 rnd = msd/2;
|
||||
int kk = precision;
|
||||
while( kk-- > 0 ){ rnd /= 10; }
|
||||
longvalue += rnd;
|
||||
}
|
||||
}else{
|
||||
msd = 0;
|
||||
longvalue = 0; /* To prevent a compiler warning */
|
||||
idx = precision & 0xfff;
|
||||
rounder = arRound[idx%10];
|
||||
while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; }
|
||||
if( xtype==etFLOAT ){
|
||||
double rx = (double)realvalue;
|
||||
sqlite3_uint64 u;
|
||||
int ex;
|
||||
memcpy(&u, &rx, sizeof(u));
|
||||
ex = -1023 + (int)((u>>52)&0x7ff);
|
||||
if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16;
|
||||
realvalue += rounder;
|
||||
}
|
||||
if( sqlite3IsNaN((double)realvalue) ){
|
||||
if( flag_zeropad ){
|
||||
bufpt = "null";
|
||||
length = 4;
|
||||
}else{
|
||||
bufpt = "NaN";
|
||||
length = 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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++; }
|
||||
realvalue /= scale;
|
||||
while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
|
||||
while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
|
||||
if( exp>350 ){
|
||||
if( flag_zeropad ){
|
||||
realvalue = 9.0;
|
||||
exp = 999;
|
||||
}else{
|
||||
bufpt = buf;
|
||||
buf[0] = prefix;
|
||||
memcpy(buf+(prefix!=0),"Inf",4);
|
||||
length = 3+(prefix!=0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( xtype!=etFLOAT ){
|
||||
realvalue += rounder;
|
||||
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
|
||||
}
|
||||
}
|
||||
}
|
||||
exp = s.iDP-1;
|
||||
if( xtype==etGENERIC && precision>0 ) precision--;
|
||||
|
||||
/*
|
||||
** If the field type is etGENERIC, then convert to either etEXP
|
||||
@@ -642,9 +553,8 @@ void sqlite3_str_vappendf(
|
||||
if( xtype==etEXP ){
|
||||
e2 = 0;
|
||||
}else{
|
||||
e2 = exp;
|
||||
e2 = s.iDP - 1;
|
||||
}
|
||||
nsd = 16 + flag_altform2*10;
|
||||
bufpt = buf;
|
||||
{
|
||||
i64 szBufNeeded; /* Size of a temporary buffer needed */
|
||||
@@ -662,16 +572,12 @@ void sqlite3_str_vappendf(
|
||||
*(bufpt++) = prefix;
|
||||
}
|
||||
/* Digits prior to the decimal point */
|
||||
j = 0;
|
||||
if( e2<0 ){
|
||||
*(bufpt++) = '0';
|
||||
}else if( msd>0 ){
|
||||
for(; e2>=0; e2--){
|
||||
*(bufpt++) = et_getdigit_int(&longvalue,&msd);
|
||||
if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
|
||||
}
|
||||
}else{
|
||||
for(; e2>=0; e2--){
|
||||
*(bufpt++) = et_getdigit(&realvalue,&nsd);
|
||||
*(bufpt++) = j<s.n ? s.z[j++] : '0';
|
||||
if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
|
||||
}
|
||||
}
|
||||
@@ -681,19 +587,12 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
/* "0" digits after the decimal point but before the first
|
||||
** significant digit of the number */
|
||||
for(e2++; e2<0; precision--, e2++){
|
||||
assert( precision>0 );
|
||||
for(e2++; e2<0 && precision>0; precision--, e2++){
|
||||
*(bufpt++) = '0';
|
||||
}
|
||||
/* Significant digits after the decimal point */
|
||||
if( msd>0 ){
|
||||
while( (precision--)>0 ){
|
||||
*(bufpt++) = et_getdigit_int(&longvalue,&msd);
|
||||
}
|
||||
}else{
|
||||
while( (precision--)>0 ){
|
||||
*(bufpt++) = et_getdigit(&realvalue,&nsd);
|
||||
}
|
||||
while( (precision--)>0 ){
|
||||
*(bufpt++) = j<s.n ? s.z[j++] : '0';
|
||||
}
|
||||
/* Remove trailing zeros and the "." if no digits follow the "." */
|
||||
if( flag_rtz && flag_dp ){
|
||||
@@ -709,6 +608,7 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
/* Add the "eNNN" suffix */
|
||||
if( xtype==etEXP ){
|
||||
exp = s.iDP - 1;
|
||||
*(bufpt++) = aDigits[infop->charset];
|
||||
if( exp<0 ){
|
||||
*(bufpt++) = '-'; exp = -exp;
|
||||
@@ -742,8 +642,8 @@ void sqlite3_str_vappendf(
|
||||
while( nPad-- ) bufpt[i++] = '0';
|
||||
length = width;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
|
||||
break;
|
||||
}
|
||||
case etSIZE:
|
||||
if( !bArgList ){
|
||||
*(va_arg(ap,int*)) = pAccum->nChar;
|
||||
|
||||
+11
-2
@@ -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
|
||||
|
||||
+114
-27
@@ -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)
|
||||
**
|
||||
@@ -5343,6 +5383,57 @@ static void shellUSleepFunc(
|
||||
#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
|
||||
#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
|
||||
|
||||
/*
|
||||
** Unknown function callback
|
||||
*/
|
||||
static int shellUnknownFunction(
|
||||
void *pUserData,
|
||||
sqlite3 *db,
|
||||
const char *zFunc,
|
||||
int nArg,
|
||||
int enc
|
||||
){
|
||||
ShellState *p = (ShellState*)pUserData;
|
||||
(void)enc;
|
||||
(void)nArg;
|
||||
if( sqlite3_stricmp(zFunc,"strtod")==0 ){
|
||||
sqlite3_create_function(db, "strtod", 1, SQLITE_UTF8, 0,
|
||||
shellStrtod, 0, 0);
|
||||
}else
|
||||
if( sqlite3_stricmp(zFunc,"dtostr")==0 ){
|
||||
sqlite3_create_function(db, "dtostr", 1, SQLITE_UTF8, 0,
|
||||
shellDtostr, 0, 0);
|
||||
sqlite3_create_function(db, "dtostr", 2, SQLITE_UTF8, 0,
|
||||
shellDtostr, 0, 0);
|
||||
}else
|
||||
if( sqlite3_stricmp(zFunc,"shell_add_schema")==0 ){
|
||||
sqlite3_create_function(db, "shell_add_schema", 3, SQLITE_UTF8, 0,
|
||||
shellAddSchemaName, 0, 0);
|
||||
}else
|
||||
if( sqlite3_stricmp(zFunc,"shell_module_schema")==0 ){
|
||||
sqlite3_create_function(db, "shell_module_schema", 1, SQLITE_UTF8, 0,
|
||||
shellModuleSchema, 0, 0);
|
||||
}else
|
||||
if( sqlite3_stricmp(zFunc,"shell_putsnl")==0 ){
|
||||
sqlite3_create_function(db, "shell_putsnl", 1, SQLITE_UTF8, p,
|
||||
shellPutsFunc, 0, 0);
|
||||
}else
|
||||
if( sqlite3_stricmp(zFunc,"usleep")==0 ){
|
||||
sqlite3_create_function(db, "usleep",1,SQLITE_UTF8,0,
|
||||
shellUSleepFunc, 0, 0);
|
||||
}
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
else
|
||||
if( sqlite3_stricmp(zFunc,"edit")==0 ){
|
||||
sqlite3_create_function(db, "edit", 1, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
sqlite3_create_function(db, "edit", 2, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
}
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure the database is open. If it is not, then open it. If
|
||||
** the database fails to open, print an error message and exit.
|
||||
@@ -5463,21 +5554,9 @@ static void open_db(ShellState *p, int openFlags){
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
|
||||
shellAddSchemaName, 0, 0);
|
||||
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
|
||||
shellModuleSchema, 0, 0);
|
||||
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
|
||||
shellPutsFunc, 0, 0);
|
||||
sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
|
||||
shellUSleepFunc, 0, 0);
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
#endif
|
||||
sqlite3_function_needed(p->db, p, shellUnknownFunction, 0);
|
||||
|
||||
|
||||
if( p->openMode==SHELL_OPEN_ZIPFILE ){
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
|
||||
@@ -10532,7 +10611,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 +10884,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" },
|
||||
@@ -10829,6 +10909,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
|
||||
{"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
|
||||
{"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
|
||||
{"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
|
||||
};
|
||||
int testctrl = -1;
|
||||
int iCtrl = -1;
|
||||
@@ -10837,12 +10918,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 +10931,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 +10943,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 +10959,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){
|
||||
|
||||
@@ -10959,6 +11031,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
break;
|
||||
|
||||
/* sqlite3_test_control(int, int) */
|
||||
case SQLITE_TESTCTRL_USELONGDOUBLE: {
|
||||
int opt = -1;
|
||||
if( nArg==3 ){
|
||||
if( cli_strcmp(azArg[2],"default")==0 ){
|
||||
opt = 2;
|
||||
}else{
|
||||
opt = booleanValue(azArg[2]);
|
||||
}
|
||||
}
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
isOk = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(sqlite3*) */
|
||||
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
|
||||
rc2 = sqlite3_test_control(testctrl, p->db);
|
||||
|
||||
+50
-1
@@ -6206,6 +6206,54 @@ int sqlite3_create_collation16(
|
||||
int(*xCompare)(void*,int,const void*,int,const void*)
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Function Needed Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** The sqlite3_function_needed(D,P,C,X) interface registers a callback
|
||||
** function C which is invoked whenever the SQL parser encounters an
|
||||
** unknown SQL function. The callback may optionally register a suitable
|
||||
** implementation for that unknown function (using [sqlite3_create_function()]
|
||||
** or similar), in which case parsing will continue normally. In this way,
|
||||
** applications with hundreds or thousands of seldom-used application defined
|
||||
** SQL functions can avoid having register them at start-up and instead
|
||||
** register each function if and only if it it actually gets used.
|
||||
**
|
||||
** ^If the callback function C has been registered using the
|
||||
** sqlite3_function_needed(D,P,C,X), then whenever the SQL parser encounters
|
||||
** an unknown SQL function, it will invoke the C callback with 5 arguments:
|
||||
** P, D, F, N, E. P is a copy of the generic pointer P parameter to
|
||||
** the original sqlite3_function_needed() call that registered the
|
||||
** callback. D is the database connection. F is the name of the unknown
|
||||
** function (UTF-8 encoded and zero-terminated but in an arbitrary case).
|
||||
** N is the number of arguments on the F function.
|
||||
** E is the preferred text encoding.
|
||||
**
|
||||
** If the C callback registers a new function with the correct
|
||||
** name and number of arguments and if the callback returns SQLITE_OK, then
|
||||
** the newly registered function is used and parsing continues. If an
|
||||
** appropriate function does not get registered, or if the callback returns
|
||||
** anything other than SQLITE_OK, then an "unknown function" error is generated
|
||||
** as normal.
|
||||
**
|
||||
** Only a single function-needed callback is supported per database connection.
|
||||
** Each call to sqlite3_function_needed() replaces the callback identified
|
||||
** by the previous call to sqlite3_function_needed(). The function-needed
|
||||
** callback mechanism may be disabled by invoking sqlite3_function_needed(D,P,C,X)
|
||||
** using a NULL pointer for the C parameter.
|
||||
**
|
||||
** The X argument to sqlite3_function_needed(D,P,C,X) is an optional
|
||||
** destructor for generic pointer parameter P. If X and C are both not NULL,
|
||||
** then X(P) is invoked when the database connection closes or at the next
|
||||
** call to sqlite3_function_needed().
|
||||
*/
|
||||
int sqlite3_function_needed(
|
||||
sqlite3*,
|
||||
void*,
|
||||
int(*)(void*,sqlite3*,const char*,int,int),
|
||||
void(*)(void*)
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Collation Needed Callbacks
|
||||
** METHOD: sqlite3
|
||||
@@ -8176,7 +8224,8 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
|
||||
@@ -361,6 +361,8 @@ struct sqlite3_api_routines {
|
||||
int (*value_encoding)(sqlite3_value*);
|
||||
/* Version 3.41.0 and later */
|
||||
int (*is_interrupted)(sqlite3*);
|
||||
/* Version 3.43.0 and later */
|
||||
int (*function_needed)(sqlite3*,void*,const char*,int,int);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -689,6 +691,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
||||
/* Version 3.41.0 and later */
|
||||
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
||||
/* Version 3.43.0 and later */
|
||||
#define sqlite3_function_needed sqlite3_api->function_needed
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
@@ -1234,10 +1234,12 @@ 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;
|
||||
typedef struct FKey FKey;
|
||||
typedef struct FpDecode FpDecode;
|
||||
typedef struct FuncDestructor FuncDestructor;
|
||||
typedef struct FuncDef FuncDef;
|
||||
typedef struct FuncDefHash FuncDefHash;
|
||||
@@ -1672,6 +1674,9 @@ struct sqlite3 {
|
||||
int (*xWalCallback)(void *, sqlite3 *, const char *, int);
|
||||
void *pWalArg;
|
||||
#endif
|
||||
int(*xFuncNeeded)(void*,sqlite3*,const char*,int,int);
|
||||
void *pFuncNeededArg;
|
||||
void(*xFuncNeededFree)(void*);
|
||||
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
|
||||
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
|
||||
void *pCollNeededArg;
|
||||
@@ -1930,6 +1935,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 +1954,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 +3898,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 */
|
||||
@@ -4085,6 +4093,7 @@ struct Sqlite3Config {
|
||||
u8 bUseCis; /* Use covering indices for full-scans */
|
||||
u8 bSmallMalloc; /* Avoid large memory allocations if true */
|
||||
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
|
||||
u8 bUseLongDouble; /* Make use of long double */
|
||||
int mxStrlen; /* Maximum string length */
|
||||
int neverCorrupt; /* Database is always well-formed */
|
||||
int szLookaside; /* Default lookaside buffer size */
|
||||
@@ -4593,6 +4602,19 @@ struct PrintfArguments {
|
||||
sqlite3_value **apArg; /* The argument values */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of this object receives the decoding of a floating point
|
||||
** value into an approximate decimal representation.
|
||||
*/
|
||||
struct FpDecode {
|
||||
char sign; /* '+' or '-' */
|
||||
char isSpecial; /* 1: Infinity 2: NaN */
|
||||
int n; /* Significant digits in the decode */
|
||||
int iDP; /* Location of the decimal point */
|
||||
char z[24]; /* Significiant digits */
|
||||
};
|
||||
|
||||
void sqlite3FpDecode(FpDecode*,double,int,int);
|
||||
char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
||||
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
||||
@@ -5032,6 +5054,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*);
|
||||
|
||||
+137
-1
@@ -991,6 +991,46 @@ static void intrealFunction(
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context);
|
||||
}
|
||||
|
||||
/*
|
||||
** 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_create_function DB
|
||||
**
|
||||
@@ -1063,6 +1103,27 @@ static int SQLITE_TCLAPI test_create_function(
|
||||
0, intrealFunction, 0, 0);
|
||||
}
|
||||
|
||||
/* Functions strtod() and dtostr() work as in the shell. These routines
|
||||
** use the standard C library to convert between floating point and
|
||||
** text. This is used to compare SQLite's internal conversion routines
|
||||
** against the standard library conversion routines.
|
||||
**
|
||||
** Both routines copy/pasted from the shell.c.in implementation
|
||||
** on 2023-07-03.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "strtod", 1, SQLITE_UTF8, 0,
|
||||
shellStrtod, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "dtostr", 1, SQLITE_UTF8, 0,
|
||||
shellDtostr, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "dtostr", 2, SQLITE_UTF8, 0,
|
||||
shellDtostr, 0, 0);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also
|
||||
** because it is not tested anywhere else. */
|
||||
@@ -2216,6 +2277,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 +2285,7 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
|
||||
int flag;
|
||||
} aTbl[] = {
|
||||
{"complex", SQLITE_SCANSTAT_COMPLEX},
|
||||
{"debug", -1},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
@@ -2239,7 +2302,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 +2320,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 +2373,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);
|
||||
@@ -6994,6 +7098,37 @@ static int SQLITE_TCLAPI extra_schema_checks(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: use_long_double BOOLEAN|"default"
|
||||
**
|
||||
** If no argument, report the current value of the use-long-double flag.
|
||||
**
|
||||
** If argument is "default", set the use-long-double flag to the default
|
||||
** value for this build, based on the size of LONGDOUBLE_TYPE.
|
||||
**
|
||||
** If argument is a boolean, set the use-long-double flag accordingly.
|
||||
**
|
||||
** Return the new setting.
|
||||
*/
|
||||
static int SQLITE_TCLAPI use_long_double(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int i = -1;
|
||||
if( objc==2 ){
|
||||
if( strcmp(Tcl_GetString(objv[1]),"default")==0 ){
|
||||
i = 2;
|
||||
}else{
|
||||
if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
i = sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, i);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: database_may_be_corrupt
|
||||
**
|
||||
@@ -8882,6 +9017,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "reset_prng_state", reset_prng_state, 0 },
|
||||
{ "prng_seed", prng_seed, 0 },
|
||||
{ "extra_schema_checks", extra_schema_checks, 0},
|
||||
{ "use_long_double", use_long_double, 0},
|
||||
{ "database_never_corrupt", database_never_corrupt, 0},
|
||||
{ "database_may_be_corrupt", database_may_be_corrupt, 0},
|
||||
{ "optimization_control", optimization_control,0},
|
||||
|
||||
+235
-102
@@ -386,43 +386,40 @@ u8 sqlite3StrIHash(const char *z){
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute 10 to the E-th power. Examples: E==1 results in 10.
|
||||
** E==2 results in 100. E==50 results in 1.0e50.
|
||||
/* Double-Double multiplication. (x[0],x[1]) *= (y,yy)
|
||||
**
|
||||
** This routine only works for values of E between 1 and 341.
|
||||
** Reference:
|
||||
** T. J. Dekker, "A Floating-Point Technique for Extending the
|
||||
** Available Precision". 1971-07-26.
|
||||
*/
|
||||
static LONGDOUBLE_TYPE sqlite3Pow10(int E){
|
||||
#if defined(_MSC_VER)
|
||||
static const LONGDOUBLE_TYPE x[] = {
|
||||
1.0e+001L,
|
||||
1.0e+002L,
|
||||
1.0e+004L,
|
||||
1.0e+008L,
|
||||
1.0e+016L,
|
||||
1.0e+032L,
|
||||
1.0e+064L,
|
||||
1.0e+128L,
|
||||
1.0e+256L
|
||||
};
|
||||
LONGDOUBLE_TYPE r = 1.0;
|
||||
int i;
|
||||
assert( E>=0 && E<=307 );
|
||||
for(i=0; E!=0; i++, E >>=1){
|
||||
if( E & 1 ) r *= x[i];
|
||||
}
|
||||
return r;
|
||||
#else
|
||||
LONGDOUBLE_TYPE x = 10.0;
|
||||
LONGDOUBLE_TYPE r = 1.0;
|
||||
while(1){
|
||||
if( E & 1 ) r *= x;
|
||||
E >>= 1;
|
||||
if( E==0 ) break;
|
||||
x *= x;
|
||||
}
|
||||
return r;
|
||||
#endif
|
||||
static void dekkerMul2(volatile double *x, double y, double yy){
|
||||
/*
|
||||
** The "volatile" keywords on parameter x[] and on local variables
|
||||
** below are needed force intermediate results to be truncated to
|
||||
** binary64 rather than be carried around in an extended-precision
|
||||
** format. The truncation is necessary for the Dekker algorithm to
|
||||
** work. Intel x86 floating point might omit the truncation without
|
||||
** the use of volatile.
|
||||
*/
|
||||
volatile double tx, ty, p, q, c, cc;
|
||||
double hx, hy;
|
||||
u64 m;
|
||||
memcpy(&m, (void*)&x[0], 8);
|
||||
m &= 0xfffffffffc000000L;
|
||||
memcpy(&hx, &m, 8);
|
||||
tx = x[0] - hx;
|
||||
memcpy(&m, &y, 8);
|
||||
m &= 0xfffffffffc000000L;
|
||||
memcpy(&hy, &m, 8);
|
||||
ty = y - hy;
|
||||
p = hx*hy;
|
||||
q = hx*ty + tx*hy;
|
||||
c = p+q;
|
||||
cc = p - c + q + tx*ty;
|
||||
cc = x[0]*yy + x[1]*y + cc;
|
||||
x[0] = c + cc;
|
||||
x[1] = c - x[0];
|
||||
x[1] += cc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -463,12 +460,11 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
const char *zEnd;
|
||||
/* sign * significand * (10 ^ (esign * exponent)) */
|
||||
int sign = 1; /* sign of significand */
|
||||
i64 s = 0; /* significand */
|
||||
u64 s = 0; /* significand */
|
||||
int d = 0; /* adjust exponent for shifting decimal point */
|
||||
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;
|
||||
int nDigit = 0; /* Number of digits processed */
|
||||
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
|
||||
|
||||
@@ -508,7 +504,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
s = s*10 + (*z - '0');
|
||||
z+=incr; nDigit++;
|
||||
if( s>=((LARGEST_INT64-9)/10) ){
|
||||
if( s>=((LARGEST_UINT64-9)/10) ){
|
||||
/* skip non-significant significand digits
|
||||
** (increase exponent by d to shift decimal left) */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
|
||||
@@ -523,7 +519,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
/* copy digits from after decimal to significand
|
||||
** (decrease exponent by d to shift decimal right) */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
if( s<((LARGEST_INT64-9)/10) ){
|
||||
if( s<((LARGEST_UINT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
d--;
|
||||
nDigit++;
|
||||
@@ -563,78 +559,79 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
|
||||
do_atof_calc:
|
||||
/* Zero is a special case */
|
||||
if( s==0 ){
|
||||
*pResult = sign<0 ? -0.0 : +0.0;
|
||||
goto atof_return;
|
||||
}
|
||||
|
||||
/* adjust exponent by d, and update sign */
|
||||
e = (e*esign) + d;
|
||||
if( e<0 ) {
|
||||
esign = -1;
|
||||
e *= -1;
|
||||
} else {
|
||||
esign = 1;
|
||||
|
||||
/* Try to adjust the exponent to make it smaller */
|
||||
while( e>0 && s<(LARGEST_UINT64/10) ){
|
||||
s *= 10;
|
||||
e--;
|
||||
}
|
||||
while( e<0 && (s%10)==0 ){
|
||||
s /= 10;
|
||||
e++;
|
||||
}
|
||||
|
||||
if( s==0 ) {
|
||||
/* In the IEEE 754 standard, zero is signed. */
|
||||
result = sign<0 ? -(double)0 : (double)0;
|
||||
} else {
|
||||
/* Attempt to reduce exponent.
|
||||
**
|
||||
** Branches that are not required for the correct answer but which only
|
||||
** help to obtain the correct answer faster are marked with special
|
||||
** comments, as a hint to the mutation tester.
|
||||
*/
|
||||
while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
if( esign>0 ){
|
||||
if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
|
||||
s *= 10;
|
||||
}else{
|
||||
if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
|
||||
s /= 10;
|
||||
}
|
||||
e--;
|
||||
}
|
||||
|
||||
/* adjust the sign of significand */
|
||||
s = sign<0 ? -s : s;
|
||||
|
||||
if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
result = (double)s;
|
||||
if( e==0 ){
|
||||
*pResult = s;
|
||||
}else if( sqlite3Config.bUseLongDouble ){
|
||||
LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
|
||||
if( e>0 ){
|
||||
while( e>=100 ){ e-=100; r *= 1.0e+100L; }
|
||||
while( e>=10 ){ e-=10; r *= 1.0e+10L; }
|
||||
while( e>=1 ){ e-=1; r *= 1.0e+01L; }
|
||||
}else{
|
||||
/* attempt to handle extremely small/large numbers better */
|
||||
if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
|
||||
if( esign<0 ){
|
||||
result = s / scale;
|
||||
result /= 1.0e+308;
|
||||
}else{
|
||||
result = s * scale;
|
||||
result *= 1.0e+308;
|
||||
}
|
||||
}else{ assert( e>=342 );
|
||||
if( esign<0 ){
|
||||
result = 0.0*s;
|
||||
}else{
|
||||
#ifdef INFINITY
|
||||
result = INFINITY*s;
|
||||
#else
|
||||
result = 1e308*1e308*s; /* Infinity */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}else{
|
||||
LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
|
||||
if( esign<0 ){
|
||||
result = s / scale;
|
||||
}else{
|
||||
result = s * scale;
|
||||
}
|
||||
while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
|
||||
while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
|
||||
while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
|
||||
}
|
||||
*pResult = r;
|
||||
}else{
|
||||
double rr[2];
|
||||
u64 s2;
|
||||
rr[0] = (double)s;
|
||||
s2 = (u64)rr[0];
|
||||
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
||||
if( e>0 ){
|
||||
while( e>=100 ){
|
||||
e -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( e>=10 ){
|
||||
e -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( e>=1 ){
|
||||
e -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
}else{
|
||||
while( e<=-100 ){
|
||||
e += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( e<=-10 ){
|
||||
e += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( e<=-1 ){
|
||||
e += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
}
|
||||
*pResult = rr[0]+rr[1];
|
||||
if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
|
||||
}
|
||||
if( sign<0 ) *pResult = -*pResult;
|
||||
assert( !sqlite3IsNaN(*pResult) );
|
||||
|
||||
/* store the result */
|
||||
*pResult = result;
|
||||
|
||||
atof_return:
|
||||
/* return true if number and no extra non-whitespace characters after */
|
||||
if( z==zEnd && nDigit>0 && eValid && eType>0 ){
|
||||
return eType;
|
||||
@@ -928,6 +925,142 @@ int sqlite3Atoi(const char *z){
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decode a floating-point value into an approximate decimal
|
||||
** representation.
|
||||
**
|
||||
** Round the decimal representation to n significant digits if
|
||||
** n is positive. Or round to -n signficant digits after the
|
||||
** decimal point if n is negative. No rounding is performed if
|
||||
** n is zero.
|
||||
*/
|
||||
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
int i;
|
||||
u64 v;
|
||||
int e, exp = 0;
|
||||
p->isSpecial = 0;
|
||||
|
||||
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
||||
** NaN. */
|
||||
if( r<0.0 ){
|
||||
p->sign = '-';
|
||||
r = -r;
|
||||
}else if( r==0.0 ){
|
||||
p->sign = '+';
|
||||
p->n = 1;
|
||||
p->iDP = 1;
|
||||
p->z[0] = '0';
|
||||
return;
|
||||
}else{
|
||||
p->sign = '+';
|
||||
}
|
||||
memcpy(&v,&r,8);
|
||||
e = v>>52;
|
||||
if( (e&0x7ff)==0x7ff ){
|
||||
p->isSpecial = 1 + (v!=0x7ff0000000000000L);
|
||||
p->n = 0;
|
||||
p->iDP = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Multiply r by powers of ten until it lands somewhere in between
|
||||
** 1.0e+19 and 1.0e+17.
|
||||
*/
|
||||
if( sqlite3Config.bUseLongDouble ){
|
||||
LONGDOUBLE_TYPE rr = r;
|
||||
if( rr>=1.0e+19 ){
|
||||
while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
|
||||
while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
|
||||
while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
|
||||
}else{
|
||||
while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
|
||||
while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
|
||||
while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
|
||||
}
|
||||
v = (u64)rr;
|
||||
}else{
|
||||
/* If high-precision floating point is not available using "long double",
|
||||
** then use Dekker-style double-double computation to increase the
|
||||
** precision.
|
||||
**
|
||||
** The error terms on constants like 1.0e+100 computed using the
|
||||
** decimal extension, for example as follows:
|
||||
**
|
||||
** SELECT decimal_sci(decimal_sub('1.0e+100',decimal(1.0e+100)));
|
||||
*/
|
||||
double rr[2];
|
||||
rr[0] = r;
|
||||
rr[1] = 0.0;
|
||||
if( rr[0]>1.84e+19 ){
|
||||
while( rr[0]>1.84e+119 ){
|
||||
exp += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( rr[0]>1.84e+29 ){
|
||||
exp += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( rr[0]>1.84e+19 ){
|
||||
exp += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
}else{
|
||||
while( rr[0]<1.84e-82 ){
|
||||
exp -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( rr[0]<1.84e+08 ){
|
||||
exp -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( rr[0]<1.84e+18 ){
|
||||
exp -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
}
|
||||
v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
|
||||
}
|
||||
|
||||
|
||||
/* Extract significant digits. */
|
||||
i = sizeof(p->z)-1;
|
||||
while( v ){ p->z[i--] = (v%10) + '0'; v /= 10; }
|
||||
p->n = sizeof(p->z) - 1 - i;
|
||||
p->iDP = p->n + exp;
|
||||
if( iRound<0 ){
|
||||
iRound = p->iDP - iRound;
|
||||
if( iRound==0 && p->z[i+1]>='5' ){
|
||||
iRound = 1;
|
||||
p->z[i--] = '0';
|
||||
p->n++;
|
||||
p->iDP++;
|
||||
}
|
||||
}
|
||||
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
|
||||
char *z = &p->z[i+1];
|
||||
if( iRound>mxRound ) iRound = mxRound;
|
||||
p->n = iRound;
|
||||
if( z[iRound]>='5' ){
|
||||
int j = iRound-1;
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
z[j]++;
|
||||
if( z[j]<='9' ) break;
|
||||
z[j] = '0';
|
||||
if( j==0 ){
|
||||
p->z[i--] = '1';
|
||||
p->n++;
|
||||
p->iDP++;
|
||||
break;
|
||||
}else{
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memmove(p->z, &p->z[i+1], p->n);
|
||||
while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to convert z into an unsigned 32-bit integer. Return true on
|
||||
** success and false if there is an error.
|
||||
|
||||
+9
-5
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-34
@@ -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
|
||||
**
|
||||
@@ -761,8 +731,8 @@ int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
|
||||
** from UBSAN.
|
||||
*/
|
||||
i64 sqlite3RealToI64(double r){
|
||||
if( r<=(double)SMALLEST_INT64 ) return SMALLEST_INT64;
|
||||
if( r>=(double)LARGEST_INT64) return LARGEST_INT64;
|
||||
if( r<-9223372036854774784.0 ) return SMALLEST_INT64;
|
||||
if( r>+9223372036854774784.0 ) return LARGEST_INT64;
|
||||
return (i64)r;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -15,18 +15,10 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
if {$::longdouble_size<=8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
if {$::tcl_platform(machine)!="x86_64"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set mxpow [expr {[use_long_double]?100:35}]
|
||||
expr srand(1)
|
||||
for {set i 1} {$i<20000} {incr i} {
|
||||
set pow [expr {int((rand()-0.5)*100)}]
|
||||
set pow [expr {int((rand()-0.5)*$mxpow)}]
|
||||
set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
|
||||
set xf [format %.32e $x]
|
||||
|
||||
@@ -51,10 +43,16 @@ for {set i 1} {$i<20000} {incr i} {
|
||||
set y [db eval {SELECT $x=CAST(quote($x) AS real)}]
|
||||
if {!$y} {
|
||||
db eval {SELECT real2hex($x) a, real2hex(CAST(quote($x) AS real)) b} {}
|
||||
puts "\nIN: $a $xf"
|
||||
puts [format {QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]]
|
||||
puts ""
|
||||
if {$x<0} {
|
||||
puts "[format {!SCALE: %17s 1 23456789 123456789 123456789} {}]"
|
||||
} else {
|
||||
puts "[format {!SCALE: %16s 1 23456789 123456789 123456789} {}]"
|
||||
}
|
||||
puts "!IN: $a $xf"
|
||||
puts [format {!QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]]
|
||||
db eval {SELECT CAST(quote($x) AS real) c} {}
|
||||
puts "OUT: $b [format %.32e $c]"
|
||||
puts "!OUT: $b [format %.32e $c]"
|
||||
}
|
||||
set y
|
||||
} {1}
|
||||
|
||||
+16
-9
@@ -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)
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** Performance testing of floating-point binary-to-decimal conversion for
|
||||
** SQLite versus the standard library.
|
||||
**
|
||||
** To compile:
|
||||
**
|
||||
** make sqlite3.c
|
||||
** gcc -Os -c sqlite3.c
|
||||
** gcc -I. -Os test/fp-speed-1.c sqlite3.o -ldl -lm -lpthread
|
||||
**
|
||||
** To run the test:
|
||||
**
|
||||
** time ./a.out 0 10000000 <-- standard library
|
||||
** time ./a.out 1 10000000 <-- SQLite
|
||||
** time ./a.out 2 10000000 <-- SQLite with long-double disabled
|
||||
*/
|
||||
static double aVal[] = {
|
||||
-1.0163830486285643089e+063,
|
||||
+0.0049243807391586981e-019,
|
||||
+7.3818732407343994867e-095,
|
||||
+7.0678595219225717143e+000,
|
||||
+9.2807266319850025655e+120,
|
||||
+5.8871050861933394663e+135,
|
||||
-2.2998023621259662805e-168,
|
||||
-1.5903581924910847482e+181,
|
||||
+2.4313441816844978216e-001,
|
||||
-3.8290987328945399091e-147,
|
||||
+1.8787914062744001349e-009,
|
||||
+0.7270653560487146653e-014,
|
||||
+0.0639577697913183665e+107,
|
||||
+5.2292338879315861930e-103,
|
||||
+6.3747682672872231319e-021,
|
||||
+8.6972339538329106984e-129,
|
||||
-9.5074486051597691937e-026,
|
||||
-8.6480257845368753018e-005,
|
||||
-3.5657595775797470332e+017,
|
||||
-7.8323106179731761351e+161,
|
||||
+7.7813875274120800372e+077,
|
||||
-1.8739718928360196596e-050,
|
||||
+8.6898145915593357218e-051,
|
||||
+6.0566766359877837871e+002,
|
||||
+4.1703379217148160678e+199,
|
||||
+2.1283871288746651560e+150,
|
||||
-6.8395236083891810637e+128,
|
||||
-6.2114299763939529155e-147,
|
||||
-2.0753525742614637350e-149,
|
||||
+5.8727459803944290257e-007,
|
||||
+8.5888991062002101817e+010,
|
||||
+6.8624461031355917632e+026,
|
||||
-3.3053986756670905167e-075,
|
||||
-4.3596843152763444945e-108,
|
||||
+0.0834139520104099673e+098,
|
||||
-8.8581986548904222440e-192,
|
||||
-3.6622095428727698202e+038,
|
||||
-6.6965852297025063260e+005,
|
||||
+1.8204169347406488441e-054,
|
||||
+6.5234508038649000384e-065,
|
||||
+1.5923006018219011453e+083,
|
||||
+1.7362555291656389480e+018,
|
||||
+7.2875431976854785882e+160,
|
||||
+1.2835880105958926748e-146,
|
||||
+8.0516253320320819420e-113,
|
||||
+6.6324633399381145440e-030,
|
||||
-1.7126500070280062058e-149,
|
||||
+1.6995738341583712335e+042,
|
||||
+7.6048766923738663725e-112,
|
||||
+0.6159117235449455043e-004,
|
||||
+5.7544894355415943289e-135,
|
||||
+8.2970228592690581890e-023,
|
||||
-6.5531925360163067447e+020,
|
||||
+5.8321334606187030050e+120,
|
||||
+5.6557166509571891727e+095,
|
||||
+0.3322789708438408704e-114,
|
||||
-7.1210648776698686623e-050,
|
||||
-9.6721262526706343301e+179,
|
||||
-3.4583916571377395084e-106,
|
||||
+4.7896094323214750793e-172,
|
||||
-9.6926028040004137875e-056,
|
||||
+7.0683848275381385483e-198,
|
||||
-5.2970114182162961964e-007,
|
||||
-4.4287021200905393271e-170,
|
||||
+0.0728891155732808799e-189,
|
||||
-9.1855462025879447465e+175,
|
||||
+3.7294126234131007796e+015,
|
||||
+2.6857421882792719241e+003,
|
||||
-4.7070607333624685339e+039,
|
||||
+7.2175820768279334274e+136,
|
||||
-8.3678412534261163481e-115,
|
||||
+2.2174844304241822163e+019,
|
||||
+0.1949824588606861016e+112,
|
||||
-9.7334052955672071912e+151,
|
||||
-9.7793887766936999879e-142,
|
||||
-5.1561164587416931561e+139,
|
||||
-7.5048993577765174789e-022,
|
||||
+7.3556076568687784568e+107,
|
||||
-5.0681628575533599865e-144,
|
||||
+1.5209705642027747811e+165,
|
||||
-7.5989782535048296040e-101,
|
||||
+1.3654137203389775871e-016,
|
||||
-1.6441720554651372066e+087,
|
||||
-4.9042433196141125923e+000,
|
||||
-7.7063611961649130777e+118,
|
||||
+0.1699427460930766201e+174,
|
||||
+8.3374317849572216870e-145,
|
||||
-5.2355330480469580072e+081,
|
||||
-3.8510045942194147919e+141,
|
||||
-6.3513622544326339887e-147,
|
||||
+2.3869303484454428988e+049,
|
||||
+3.8352715871620360268e-165,
|
||||
-3.1263120493136887902e+035,
|
||||
-5.5794797002556490823e+051,
|
||||
-8.8109874479595604379e+142,
|
||||
-4.3727360120203216922e+070,
|
||||
-3.1109951189668539974e+170,
|
||||
-9.4841878031704268232e+011,
|
||||
-3.7398451668304407277e+067,
|
||||
+4.8984042008915959963e-091,
|
||||
};
|
||||
#define NN (sizeof(aVal)/sizeof(aVal[0]))
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i;
|
||||
int cnt;
|
||||
int fg;
|
||||
char zBuf[1000];
|
||||
|
||||
if( argc!=3 ){
|
||||
fprintf(stderr, "Usage: %s FLAG COUNT\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
cnt = atoi(argv[2]);
|
||||
fg = atoi(argv[1]);
|
||||
|
||||
switch( fg % 3 ){
|
||||
case 0: {
|
||||
printf("Doing %d calls to C-lib sprintf()\n", cnt);
|
||||
for(i=0; i<cnt; i++){
|
||||
sprintf(zBuf, "%.26g", aVal[i%NN]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
printf("Doing %d calls to sqlite3_snprintf()\n", cnt);
|
||||
for(i=0; i<cnt; i++){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.26g", aVal[i%NN]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
printf("Doing %d calls to sqlite3_snprintf() without long double\n", cnt);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, 0);
|
||||
for(i=0; i<cnt; i++){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.26g", aVal[i%NN]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# 2023-07-03
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains a test that attempts to verify the claim that the
|
||||
# floatpoint-to-text conversion routines built into SQLite maintain at
|
||||
# least 15 significant digits of accuracy.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
if {[catch {load_static_extension db decimal} error]} {
|
||||
puts "Skipping decimal tests, hit load error: $error"
|
||||
finish_test; return
|
||||
}
|
||||
|
||||
sqlite3_create_function db
|
||||
do_execsql_test fpconv1-1.0 {
|
||||
WITH RECURSIVE
|
||||
/* Number of random floating-point values to try.
|
||||
** On a circa 2016 x64 linux box, this test runs at
|
||||
** about 80000 cases per second -------------------vvvvvv */
|
||||
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100000),
|
||||
fp(y) AS MATERIALIZED (
|
||||
SELECT CAST( format('%+d.%019d0e%+03d',
|
||||
random()%10,abs(random()),random()%200) AS real)
|
||||
FROM c
|
||||
)
|
||||
SELECT y FROM fp
|
||||
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<15.0;
|
||||
/* Number of digits of accuracy required -------^^^^ */
|
||||
} {}
|
||||
# ^---- Expect a empty set as the result. The output is all tested numbers
|
||||
# that fail to preserve at least 15 significant digits of accuracy.
|
||||
|
||||
finish_test
|
||||
+47
-24
@@ -42,6 +42,10 @@ do_test func-0.1 {
|
||||
do_test func-1.0 {
|
||||
execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
|
||||
} {4 2 7 8 4}
|
||||
set isutf16 [regexp 16 [db one {PRAGMA encoding}]]
|
||||
do_execsql_test func-1.0b {
|
||||
SELECT octet_length(t1) FROM tbl1 ORDER BY t1;
|
||||
} [expr {$isutf16?"8 4 14 16 8":"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 +61,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);
|
||||
} [expr {(1+($isutf16!=0))*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);
|
||||
} [expr {(1+($isutf16!=0))*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 +863,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 +1527,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
|
||||
|
||||
@@ -257,6 +257,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DLONGDOUBLE_TYPE=double
|
||||
-DCONFIG_SLOWDOWN_FACTOR=8.0
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ for {set iTest 1} {$iTest<=50000} {incr iTest} {
|
||||
set r2 $x1.$x4
|
||||
set ans [string trimright $r2 0]
|
||||
if {[string match *. $ans]} {set ans ${ans}0}
|
||||
do_test $iTest/$n/${r}5=>$ans {
|
||||
set x [db one "SELECT round(${r}5,$n)"]
|
||||
do_test $iTest/$n/${r}6=>$ans {
|
||||
set x [db one "SELECT round(${r}6,$n)"]
|
||||
} $ans
|
||||
}
|
||||
|
||||
|
||||
+65
-4
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,6 +21,7 @@ static const char zHelp[] =
|
||||
" --memdb Use an in-memory database\n"
|
||||
" --mmap SZ MMAP the first SZ bytes of the database file\n"
|
||||
" --multithread Set multithreaded mode\n"
|
||||
" --nolongdouble Disable the use of long double\n"
|
||||
" --nomemstat Disable memory statistics\n"
|
||||
" --nomutex Open db with SQLITE_OPEN_NOMUTEX\n"
|
||||
" --nosync Set PRAGMA synchronous=OFF\n"
|
||||
@@ -2307,6 +2308,10 @@ int main(int argc, char **argv){
|
||||
ARGC_VALUE_CHECK(1);
|
||||
mmapSize = integerValue(argv[++i]);
|
||||
#endif
|
||||
}else if( strcmp(z,"nolongdouble")==0 ){
|
||||
#ifdef SQLITE_TESTCTRL_USELONGDOUBLE
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, 0);
|
||||
#endif
|
||||
}else if( strcmp(z,"nomutex")==0 ){
|
||||
openFlags |= SQLITE_OPEN_NOMUTEX;
|
||||
}else if( strcmp(z,"nosync")==0 ){
|
||||
|
||||
@@ -99,6 +99,9 @@ while test "$1" != ""; do
|
||||
--stmtcache)
|
||||
shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1"
|
||||
;;
|
||||
--nolongdouble)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --nolongdouble"
|
||||
;;
|
||||
--checkpoint)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint"
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user