Compare commits

...

22 Commits

Author SHA1 Message Date
drh 8642ca2025 New sqlite3_db_config(SQLITE_DBCONFIG_FP_DIGITS) that let's the application
specify the number of significant digits that double→text conversions
will attempt to preserve.

FossilOrigin-Name: 3f16985dcc47a366b54164c5024f920a79dddd76faeac5e36b4770732ed72c0a
2026-02-21 19:26:58 +00:00
drh 699959ff25 New test cases for floating-point conversions.
FossilOrigin-Name: 3033fe97b14ba0531278d4aa444bc5340e044b87a72b3a4341032ddee442000f
2026-02-21 13:57:40 +00:00
drh 7aba858597 Remove an unreachable branch.
FossilOrigin-Name: 93f90eacc0c5b2ae0042ec525359298883f8473e24967208feef4029d9fa2d08
2026-02-21 13:40:07 +00:00
drh 4428aa842c Increase the precision of double → text conversions that happen in
sqlite3_column_text(), or sqlite3_value_text(), or in the CAST() operator,
or similar, so that round-tripping the value back to double results in
exactly the same value.

FossilOrigin-Name: ef0049e3ade304f64e1ab97e52e1e21379e4db461f3fa80dac8e544fb90d622f
2026-02-21 10:57:02 +00:00
drh 24ef9fbb19 Further simplification, performance gain, and size reduction in
sqlite3FpDecode().

FossilOrigin-Name: 5954f22ceb6b43ed160ec085cd86b66299d8aab3e349a41941a4f1c2eade7457
2026-02-21 00:56:11 +00:00
drh aec283385e Small performance increase and size reduction in sqlite3FpDecode() by using
local variables instead of structure elements.

FossilOrigin-Name: b4c378bba582205aa676e45b21ffa17ad6199e2a017ec73cf41a0243f693b589
2026-02-21 00:20:29 +00:00
drh ac5ee556eb Inconsequential changes to floating-point conversion, amounting to mere
code cleanup to aid comprehension.

FossilOrigin-Name: 6d9c29123b6b143b0f7c8f5d018f170c72edfc5b1a4d67edd45e5552def2af6c
2026-02-20 20:43:25 +00:00
drh 62546d4b1f In the decimal extension, an optional second argument to the
decimal() and decimal_exp() functions rounds the value to the
number of significant digits specified by that argument.

FossilOrigin-Name: cb24edf1afc3f9083a4963c5fe232933eccc7c0cb8872aa5fcd336d226b885ef
2026-02-20 16:21:58 +00:00
stephan 9e395efec6 Fix a cse in the fiddle.debug build where it could not overwrite its read-only/generated index.html.
FossilOrigin-Name: 7adb2c0f438a97d377760436b1ac81fffab36e541a2b5ee733bfc7108e0180e5
2026-02-20 14:22:09 +00:00
drh d447df4205 Add new functions ieee754_to_int() and ieee754_from_int() to the
ieee754 extension.  No changes to the core SQLite.

FossilOrigin-Name: 8660d3e94cbe892693554df282bce0fa8c7aedbc5e020cab647cbbff3d7e55b7
2026-02-20 14:20:33 +00:00
drh 20c65785cd Improved rounding of floating-point conversions in some corner cases.
FossilOrigin-Name: 436dccd42650a6ab0a74459ae42fdb3e36d853f934324acc2bc961f87c001852
2026-02-20 12:27:52 +00:00
drh e8750019c2 In the CLI, the ".quit" command in a --cmd argument causes an immediate
exit.  [forum:/forumpost/f057122b68|Forum post f057122b68].

FossilOrigin-Name: 4731cc8856aa4dcfad5db501648bfd0afef43d8c5f339e7b11a1e3ee64348b87
2026-02-19 17:20:40 +00:00
drh cac09127e1 Improvements to rounding behavior in the new floating-point conversion logic.
FossilOrigin-Name: e540f6c370675ae043af8cdbb80f7eb17c08e50f7634e0b78f0b1dccf7bd4b18
2026-02-19 12:59:42 +00:00
drh 37ee141d25 Restore the CLI function dtostr() back to its original purpose of converting
floating point values to decimal using the host computer's C-library.

FossilOrigin-Name: f3cc05ba7fa9cb77573de5cd28ab90f10844567692ed57a706c5dc35b1348009
2026-02-17 20:28:25 +00:00
drh 7549e784a8 Minor fixes to tmstmpvfs.c.
FossilOrigin-Name: 091bd90ed5a6a326fd532e93bd17903e052476da14dc6aee2599a9acf75a3276
2026-02-17 14:28:18 +00:00
drh 8c3e8dce41 Increase the number of floating-point precision test cases by 9x, and
increase the require precision to 16 digits.

FossilOrigin-Name: 62c2cf74db5e47f975d1f47818f82f060ddecad4b68c4d4dbc6190cc9a8fc397
2026-02-17 14:02:27 +00:00
drh 31d4e56b29 Fix a harmless compiler warning from MSVC.
FossilOrigin-Name: 12f3a6d0aaff8818c427d79e2b9394328625b3a60ccaa7b628d064084c65cfaf
2026-02-17 12:23:12 +00:00
drh 530f536ce7 New assert()s for the return value from sqlite3SchemaToIndex().
FossilOrigin-Name: 2610105a439e25c050b2deb32953861187c81b1d97407f41dc188e6627e0ac4d
2026-02-17 11:28:48 +00:00
drh eb8c4c5742 Further simplifications, performance improvements, and size reductions
to the numeric to text conversion logic.

FossilOrigin-Name: dd5af703e1082951a4295a3453611db12b23cfbcfee4258ec3985abe96ab54ba
2026-02-17 01:04:23 +00:00
drh 0b5e944480 Faster conversion of integers to text, by converting two digits at a time.
FossilOrigin-Name: 90300e02f0de45b57d53976cae72928b3e56532d90b8b8cdc988e14762777930
2026-02-17 00:37:12 +00:00
drh 63338e3ba8 Simplifications to sqlite3AtoF(), resulting in slightly faster performance
and slightly smaller size.

FossilOrigin-Name: 6b9ab641763bc1620a01beec71589506b3b0827bff1c6cd98a5d17c6070050b3
2026-02-16 23:52:51 +00:00
dan 1105c33900 Fix another case where SQLite might fail to identify an ON clause on a RIGHT or FULL join that refers to FROM-clause elements to its right.
FossilOrigin-Name: e956b36063e77b5ad0d8b8afb5dc942665f570d762929ff277e320c06ded8ce6
2026-02-16 16:56:25 +00:00
22 changed files with 455 additions and 162 deletions
+39 -5
View File
@@ -291,12 +291,36 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_text(pCtx, z, i, sqlite3_free);
}
/*
** Round a decimal value to N significant digits. N must be positive.
*/
static void decimal_round(Decimal *p, int N){
int i;
int nZero;
if( N<1 ) return;
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
N += nZero;
if( p->nDigit<=N ) return;
if( p->a[N]>4 ){
p->a[N-1]++;
for(i=N-1; i>0 && p->a[i]>9; i--){
p->a[i] = 0;
p->a[i-1]++;
}
if( p->a[0]>9 ){
p->a[0] = 1;
p->nFrac--;
}
}
memset(&p->a[N], 0, p->nDigit - N);
}
/*
** 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 decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){
char *z; /* The output buffer */
int i; /* Loop counter */
int nZero; /* Number of leading zeros */
@@ -314,8 +338,10 @@ static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_null(pCtx);
return;
}
for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){}
if( N<1 ) N = 0;
for(nDigit=p->nDigit; nDigit>N && p->a[nDigit-1]==0; nDigit--){}
for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
N += nZero;
nFrac = p->nFrac + (nDigit - p->nDigit);
nDigit -= nZero;
z = sqlite3_malloc64( (sqlite3_int64)nDigit+20 );
@@ -677,10 +703,16 @@ static void decimalFunc(
sqlite3_value **argv
){
Decimal *p = decimal_new(context, argv[0], 0);
UNUSED_PARAMETER(argc);
int N;
if( argc==2 ){
N = sqlite3_value_int(argv[1]);
if( N>0 ) decimal_round(p, N);
}else{
N = 0;
}
if( p ){
if( sqlite3_user_data(context)!=0 ){
decimal_result_sci(context, p);
decimal_result_sci(context, p, N);
}else{
decimal_result(context, p);
}
@@ -850,7 +882,7 @@ static void decimalPow2Func(
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_result_sci(context, pA, 0);
decimal_free(pA);
}
}
@@ -871,7 +903,9 @@ int sqlite3_decimal_init(
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "decimal", 1, 0, decimalFunc },
{ "decimal", 2, 0, decimalFunc },
{ "decimal_exp", 1, 1, decimalFunc },
{ "decimal_exp", 2, 1, decimalFunc },
{ "decimal_cmp", 2, 0, decimalCmpFunc },
{ "decimal_add", 2, 0, decimalAddFunc },
{ "decimal_sub", 2, 0, decimalSubFunc },
+34
View File
@@ -259,6 +259,38 @@ static void ieee754func_to_blob(
}
}
/*
** Functions to convert between 64-bit integers and floats.
**
** The bit patterns are copied. The numeric values are different.
*/
static void ieee754func_from_int(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
double r;
sqlite3_int64 v = sqlite3_value_int64(argv[0]);
memcpy(&r, &v, sizeof(r));
sqlite3_result_double(context, r);
}
}
static void ieee754func_to_int(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ){
double r = sqlite3_value_double(argv[0]);
sqlite3_uint64 v;
memcpy(&v, &r, sizeof(v));
sqlite3_result_int64(context, v);
}
}
/*
** SQL Function: ieee754_inc(r,N)
**
@@ -311,6 +343,8 @@ 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_to_int", 1, 0, ieee754func_to_int },
{ "ieee754_from_int", 1, 0, ieee754func_from_int },
{ "ieee754_inc", 2, 0, ieee754inc },
};
unsigned int i;
+8 -4
View File
@@ -484,6 +484,7 @@ static void tmstmpPutU32(u32 v, unsigned char *a){
/* Free a TmstmpLog object */
static void tmstmpLogFree(TmstmpLog *pLog){
if( pLog==0 ) return;
if( pLog->log ) fclose(pLog->log);
sqlite3_free(pLog->zLogname);
sqlite3_free(pLog);
}
@@ -502,6 +503,7 @@ static int tmstmpLogFlush(TmstmpFile *p){
}
}
(void)fwrite(pLog->a, pLog->n, 1, pLog->log);
fflush(pLog->log);
pLog->n = 0;
return 0;
}
@@ -619,7 +621,7 @@ static int tmstmpWrite(
u32 x = 0;
p->iFrame = (iOfst - 32)/(p->pgsz+24)+1;
p->pgno = tmstmpGetU32((const u8*)zBuf);
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+16);
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+8);
memcpy(&x, ((const u8*)zBuf)+4, 4);
p->isCommit = (x!=0);
p->iOfst = iOfst;
@@ -637,7 +639,7 @@ static int tmstmpWrite(
memset(s, 0, TMSTMP_RESERVE);
tmstmpPutTS(p, s+2);
tmstmpPutU32(p->iFrame, s+8);
tmstmpPutU32(p->pPartner->salt1, s+12);
tmstmpPutU32(p->pPartner->salt1 & 0xffffff, s+12);
assert( p->pgsz>0 );
tmstmpEvent(p, ELOG_CKPT_PAGE, 0, (iOfst/p->pgsz)+1, p->iFrame, 0);
}else if( p->pPartner==0 ){
@@ -647,7 +649,7 @@ static int tmstmpWrite(
tmstmpPutTS(p, s+2);
s[12] = 2;
assert( p->pgsz>0 );
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz), 0, s+2);
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz)+1, 0, s+2);
}
return pSub->pMethods->xWrite(pSub,zBuf,iAmt,iOfst);
}
@@ -879,7 +881,9 @@ static int tmstmpOpen(
r1 = 0;
pLog = sqlite3_malloc64( sizeof(TmstmpLog) );
if( pLog==0 ){
return SQLITE_NOMEM;
pSubFile->pMethods->xClose(pSubFile);
rc = SQLITE_NOMEM;
goto tmstmp_open_done;
}
memset(pLog, 0, sizeof(pLog[0]));
p->pLog = pLog;
+1 -1
View File
@@ -206,7 +206,7 @@ b.mkdir@ = if [ ! -d $(dir $@) ]; then \
# $1 = logtag, $2 = src file(s). $3 = dest dir
b.cp = $(call b.mkdir@); \
echo '$(logtag.$(1)) $(emo.disk) $(2) ==> $3'; \
cp -p $(2) $(3) || exit
cp -f -p $(2) $(3) || exit
#
# $(call b.c-pp.shcmd,LOGTAG,src,dest,-Dx=y...)
+9 -2
View File
@@ -994,10 +994,17 @@ static void mk_fiddle(void){
pf("$(out.%s.js): $(MAKEFILE_LIST) "
"$(EXPORTED_FUNCTIONS.fiddle) "
"$(fiddle.c.in) "
"$(pre-post.%s.deps)\n",
"$(pre-post.%s.deps)",
zBuildName, zBuildName);
if( isDebug ){
pf(" $(dir.fiddle)/fiddle-worker.js"
" $(dir.fiddle)/fiddle.js"
" $(dir.fiddle)/index.html");
}
ps("");
emit_compile_start(zBuildName);
pf("\t$(b.cmd@)$(bin.emcc) -o $@"
pf("\t@$(call b.mkdir@)\n"
"\t$(b.cmd@)$(bin.emcc) -o $@"
" $(emcc.flags.%s)" /* set in GNUmakefile */
" $(pre-post.%s.flags)"
" $(fiddle.c.in)"
+24 -23
View File
@@ -1,5 +1,5 @@
C Fix\sa\sbad\sassert()\sin\sthe\sprevious\scheck-in.
D 2026-02-16T17:22:17.815
C New\ssqlite3_db_config(SQLITE_DBCONFIG_FP_DIGITS)\sthat\slet's\sthe\sapplication\nspecify\sthe\snumber\sof\ssignificant\sdigits\sthat\sdouble&rarr;text\sconversions\nwill\sattempt\sto\spreserve.
D 2026-02-21T19:26:58.856
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -370,13 +370,13 @@ F ext/misc/completion.c c27b64fdd0943c1b7f152376599814cee2641f7d67a7bb9bd2b957c2
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
F ext/misc/csv.c e82124eabee0e692d7b90ab8b2c34fadbf7b375279f102567fa06e4da4b771bf
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
F ext/misc/decimal.c d4883de142f6dcd36eda23da40b55e2b51374e7b01eb54a7173940191389fc5e
F ext/misc/decimal.c 38aa18b29e96c745c78725ef3740a53f4b2b8cdfa226dfab13aaf2168a071db7
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 452300ca34fadafd2bb9eb09557de5a518da1fd2349f9f9cedd22b1566a7164f
F ext/misc/fossildelta.c 86dfa83f85f7ccd640591d8a5c6865346d0c2ee6a949d78591eceb892f1cbfec
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c 7d7ecdd9490f6746ad88e0aa4f073ea66422341dce062d24d1b4d47d2e9050d6
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
F ext/misc/memstat.c 43705d795090efb78c85c736b89251e743c291e23daaa8382fe7a0df2c6a283d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
@@ -403,7 +403,7 @@ F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bf
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
F ext/misc/tmstmpvfs.c 3eb28a9f22f58883f38085daa312467e31ddfd2042c21dcc07173e02a01d68d8
F ext/misc/tmstmpvfs.c 240caad4441328dc52bd2871f48811db46dff858d5598030e389176837a2f4df
F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762bc3a8
F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
@@ -581,7 +581,7 @@ F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009e
F ext/session/sqlite3session.c 6ebd02be470f36d41c4bd78927f39d507b62051ba025eacaed9936c769902a07
F ext/session/sqlite3session.h 7404723606074fcb2afdc6b72c206072cdb2b7d8ba097ca1559174a80bc26f7a
F ext/session/test_session.c 190110e3bd9463717248dec1272b44fe9943e57b7646d0b4200dcf11e4dccee6
F ext/wasm/GNUmakefile a2698072853b67c39e92ca19835c65fbaa8b8884078a99c4e54b72b9ede8306e
F ext/wasm/GNUmakefile 79236447d750609aa6beda30feec1314180c5462a493ad94214122887232bfd4
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -634,7 +634,7 @@ F ext/wasm/index.html 475bc283338749db4e3fbf24cf3f5aa020cc85a1fffb780d400a915fcb
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
F ext/wasm/mkwasmbuilds.c 5d7baa9258299fd492351578a93dff960317822a08ee3ad6dd91ef5d21209812
F ext/wasm/mkwasmbuilds.c 0e9198eb90acae4bcf57cf62d7186f6af5aaac02efdb075a1aded33614b3805a
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -681,7 +681,7 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c b744bf69d520534751c742cababe7ad28c3892f1e3a75242e75a20bca15a834a
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c cc0afd3ec8417f5f774650f612e755b7ffce392d14ab4441bf5588867893fd3c
F src/build.c b993e4adef4c4cdfd7abf62e2676c467bb1923f25f40c3c7ab2a7bfbace3de7f
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
@@ -702,7 +702,7 @@ F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c 8b6341a419150b28530cc21e3951b2238c35cdc312f11b2ca29017fe4b1dedc0
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
F src/main.c e95aa130478fc98a49181ddf094baab45f319286411129253618efe0008f0dc4
F src/main.c 211f7721b191523b815dee6c6a1e9a5f3ebc052a0ddaaed24a75cf20bf9d4b06
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -734,22 +734,22 @@ F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c ecec75795c1821520266e4f93fa8840cce48979af532db06f085e36a7813860f
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
F src/printf.c b1b29b5e58e1530d5daeee5963d3c318d8ab2d7e38437580e28755753e0c1ded
F src/printf.c 9cff219dba73b1aa9a8113e83e962f03f7bea8b6eb51cefb25bc468d5a69fb2d
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 57020e1b499b7189953c59ce8a4db9fe7fdc849b47d583b1e1eb50c9dd1d1733
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 615d62112f5c14fb24facf9391492b42403875bfd4288db6ba10d7e6fbc22c4c
F src/shell.c.in b944a21d98cc4c6107bfd1ec702440579cb4bf86435125b67ff661180e9453b5
F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
F src/shell.c.in 3e87584890a4e9797865e4771689d8d1aca3b0f824f973192784716ecfa320a2
F src/sqlite.h.in b8a0b4dd92b1e52caa9676e39971bdaaf44eef30c4b148c9c2fa99e88ed6cf3a
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
F src/sqliteInt.h cd77fd03f7bf9d7b012a28c96cacdd20f09054bfe4edcebd92f789f0bc37c9fb
F src/sqliteInt.h ffa3071dc3b9172acfe1a4edd8bc699928b0d5e02f0b8b9067676aa8e5f8f787
F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c 302cc00a5f0bbfa36d73b299d600c073b02ffa7f2b59fd2c81091983ccd574a8
F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -803,7 +803,7 @@ F src/trigger.c a40440614bdf523090cc07223f4878f7e3c892bcd1a13afe18f90190daa5945d
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 16c7fcce87e43c612dd579c87d11a085ce5243565b7c324806f4a506c5e696a4
F src/util.c 95f8f7574c8f65039e341f0c905267121569ebf4d0de026c44ee1809fe00d5bf
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 5328c99dd256ee8132383565a86e253543a85daccfd7477c52f20bac6b385a7f
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
@@ -811,7 +811,7 @@ F src/vdbeInt.h 42488247a80cd9d300627833c6c85ace067ae5011a99e7614e2358130d62feea
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
F src/vdbeaux.c 396d38a62a357b807eabae0cae441fc89d2767a57ab08026b7072bf7aa2dd00c
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c bdfda8e65933cfee34aa29c2bfa31fc07609f3d56d147aa8a367a297533d33d1
F src/vdbemem.c 565c214150dbab0678bfb04db5488f1788df87aad4ec3ec71cc61e0eb3f18f38
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
@@ -872,6 +872,7 @@ F test/analyzeF.test 40b5cc3ad7b10e81020d7ca86f1417647ecfae7477cfd88acc5aa7ae106
F test/analyzeG.test 623be33038c49648872746c8dd8b23b5792c08fef173c55e82f1b12fca259852
F test/analyzer1.test b6a624ec0af92eec209e1328465b66937c8fdf2fb442a3fa45321ddb3700f4aa
F test/atof1.test bd21c4a0e718ab1470de07a2a79f2544d7903be34feebcc80de04beee4807b00
F test/atof2.test 12912add57230495450e2fc94cb8ad1c9f3277f8843a3bc27079cae45c9782a1
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
@@ -1070,7 +1071,7 @@ F test/e_createtable.test 31b9bcb6ac8876bc7ec342d86d9c231a84c62b442093a6651dfd0f
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 0a1e175caddc78b27306647cb4ce2362c55790190f8cdd178b75fd6262eb8f76
F test/e_expr.test 9bdb347b78b9f4eff9153ea97797facc179a821898588471a70808b4471a69b0
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@@ -1130,7 +1131,7 @@ F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958
F test/fork-test.c 9ac2e6423a1d38df3d6be0e8ac15608b545de21e2b19d9d876254c5931b63edb
F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
F test/fp-speed-1.c b37de94eba034e1703668816225f54510ec60fb0685406608cc707afe6b8234d
F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8
F test/fpconv1.test 63f352682fa65601a326563ad633086df6ab194e6ed5e7366786f38a525a7fd7
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
@@ -1342,7 +1343,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
F test/joinI.test f48cfbec4fd68a0d7a4498593164a4d76d622774afe896b46c223cbe15e02f55
F test/joinI.test 249802b168ce96d8d57943ef9abafc1e36e28d91829f68bc2b6e87f2b4d33241
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -2194,8 +2195,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 67c7c72e9bdf04c920d77006538a202c923fa74b47c81dc3014c2929dac7277d
R 94ab950169198f260c23800402fd70a5
P 3033fe97b14ba0531278d4aa444bc5340e044b87a72b3a4341032ddee442000f
R 4d154d27dd2b7e6c72267982eae3c18d
U drh
Z c0318b1fd81a3ec64d379bf447b9b4ea
Z 47c16a6580f94070b6e59ea57711afd7
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch numeric-conversion-perf
tag numeric-conversion-perf
branch fp-performance-v2
tag fp-performance-v2
+1 -1
View File
@@ -1 +1 @@
a4540582b5b704af13b570b3dc609dbacada719302372a038cf74eee3688d5e7
3f16985dcc47a366b54164c5024f920a79dddd76faeac5e36b4770732ed72c0a
+3
View File
@@ -486,6 +486,7 @@ Table *sqlite3LocateTableItem(
const char *zDb;
if( p->fg.fixedSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
assert( iDb>=0 && iDb<pParse->db->nDb );
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
assert( !p->fg.isSubquery );
@@ -2730,6 +2731,7 @@ void sqlite3EndTable(
convertToWithoutRowidTable(pParse, p);
}
iDb = sqlite3SchemaToIndex(db, p->pSchema);
assert( iDb>=0 && iDb<=db->nDb );
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
@@ -3025,6 +3027,7 @@ void sqlite3CreateView(
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
assert( iDb>=0 && iDb<db->nDb );
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
+9
View File
@@ -971,6 +971,14 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
case SQLITE_DBCONFIG_FP_DIGITS: {
int nIn = va_arg(ap, int);
int *pOut = va_arg(ap, int*);
if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn;
if( pOut ) *pOut = db->nFpDigit;
rc = SQLITE_OK;
break;
}
default: {
static const struct {
int op; /* The opcode */
@@ -3399,6 +3407,7 @@ static int openDatabase(
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
db->nFpDigit = 17;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
+1 -1
View File
@@ -549,7 +549,7 @@ void sqlite3_str_vappendf(
}else{
iRound = precision+1;
}
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16);
if( s.isSpecial ){
if( s.isSpecial==2 ){
bufpt = flag_zeropad ? "null" : "NaN";
+8 -8
View File
@@ -2073,6 +2073,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
/* If the SELECT statement contains ON clauses that were moved into
** the WHERE clause, go through and verify that none of the terms
** in the ON clauses reference tables to the right of the ON clause. */
if( (p->selFlags & SF_OnToWhere) ){
sqlite3SelectCheckOnClauses(pParse, p);
if( pParse->nErr ) return WRC_Abort;
}
/* Advance to the next term of the compound
*/
p = p->pPrior;
@@ -2250,14 +2258,6 @@ void sqlite3ResolveSelectNames(
w.pParse = pParse;
w.u.pNC = pOuterNC;
sqlite3WalkSelect(&w, p);
/* If the SELECT statement contains ON clauses that were moved into
** the WHERE clause, go through and verify that none of the terms
** in the ON clauses reference tables to the right of the ON clause.
** Do this now, immediately after name resolution. */
if( pParse->nErr==0 && (p->selFlags & SF_OnToWhere) ){
sqlite3SelectCheckOnClauses(pParse, p);
}
}
/*
+14 -5
View File
@@ -931,7 +931,7 @@ static void shellDtostr(
char z[400];
if( n<1 ) n = 1;
if( n>350 ) n = 350;
sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
sprintf(z, "%#+.*e", n, r);
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}
@@ -9267,6 +9267,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "fp_digits", SQLITE_DBCONFIG_FP_DIGITS },
{ "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
{ "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
@@ -9283,11 +9284,19 @@ static int do_meta_command(const char *zLine, ShellState *p){
for(ii=0; ii<ArraySize(aDbConfig); ii++){
if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
if( nArg>=3 ){
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
sqlite3_db_config(p->db, aDbConfig[ii].op, atoi(azArg[2]), 0);
}else{
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
}
}
sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
cli_printf(p->out, "%19s %s\n",
aDbConfig[ii].zName, v ? "on" : "off");
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
cli_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
}else{
cli_printf(p->out, "%19s %s\n",
aDbConfig[ii].zName, v ? "on" : "off");
}
if( nArg>1 ) break;
}
if( nArg>1 && ii==ArraySize(aDbConfig) ){
@@ -13346,7 +13355,7 @@ int SQLITE_CDECL main(int argc, char **argv){
z = cmdline_option_value(argc,argv,++i);
if( z[0]=='.' ){
rc = do_meta_command(z, &data);
if( rc && bail_on_error ){
if( rc && (bail_on_error || rc==2) ){
if( rc==2 ) rc = 0;
goto shell_main_exit;
}
+17 -1
View File
@@ -2648,6 +2648,21 @@ struct sqlite3_mem_methods {
** comments are allowed in SQL text after processing the first argument.
** </dd>
**
** [[SQLITE_DBCONFIG_FP_DIGITS]]
** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt>
** <dd>The SQLITE_DBCONFIG_FP_DIGITS option is a small integer is the number
** of significant digits that SQLite attempts to preserve when converting
** floating point numbers (IEEE 754 "doubles") into text. The default value
** (as of SQLite version 3.52.0) is 17.<p>
** This option takes two arguments which are an integer and a pointer
** to an integer. The first argument is a small integer, between 3 and 20, or
** zero. The FP_DIGITS setting is changed to the small integer, or left
** altered if the first argument is out of range. The second argument is a
** pointer to an integer. If the pointer is not NULL, then the value of
** the FP_DIGITS setting, after possibly being modified by the first
** arguments, is written into the integer to which the second argument points.
** </dd>
**
** </dl>
**
** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
@@ -2692,7 +2707,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */
#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
+4 -3
View File
@@ -1692,6 +1692,7 @@ struct sqlite3 {
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
u8 eOpenState; /* Current condition of the connection */
u8 nFpDigit; /* Significant digits to keep on double->text */
int nextPagesize; /* Pagesize after VACUUM if >0 */
i64 nChange; /* Value returned by sqlite3_changes() */
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
@@ -4820,12 +4821,12 @@ struct PrintfArguments {
** 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; /* Start of significant digits */
char zBuf[24]; /* Storage for significant digits */
char zBuf[20]; /* Storage for significant digits */
char sign; /* '+' or '-' */
char isSpecial; /* 1: Infinity 2: NaN */
};
void sqlite3FpDecode(FpDecode*,double,int,int);
+1
View File
@@ -8644,6 +8644,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
{ "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
{ "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
{ "FP_DIGITS", SQLITE_DBCONFIG_FP_DIGITS },
};
int i;
int v = 0;
+149 -91
View File
@@ -648,13 +648,18 @@ static int countLeadingZeros(u64 m){
*/
static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
int p;
u64 h, out;
u64 h;
assert( n>=1 && n<=18 );
p = n - 1 - pwr2to10(e+63);
h = sqlite3Multiply128(m, powerOfTen(p));
assert( -(e + pwr10to2(p) + 3) >=0 );
assert( -(e + pwr10to2(p) + 3) <64 );
out = h >> -(e + pwr10to2(p) + 3);
*pD = (out + 2 + ((out>>2)&1)) >> 2;
assert( -(e + pwr10to2(p) + 2) >= 0 );
assert( -(e + pwr10to2(p) + 1) <= 63 );
if( n==18 ){
h >>= -(e + pwr10to2(p) + 2);
*pD = (h + ((h<<1)&2))>>1;
}else{
*pD = h >> -(e + pwr10to2(p) + 1);
}
*pP = -p;
}
@@ -738,12 +743,9 @@ static double sqlite3Fp10Convert2(u64 d, int p){
int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of 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 */
int neg = 0; /* True for a negative value */
u64 s = 0; /* mantissa */
int d = 0; /* Value is s * pow(10,d) */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional */
@@ -754,7 +756,7 @@ int sqlite3AtoF(const char *z, double *pResult){
/* get sign of significand */
if( *z=='-' ){
sign = -1;
neg = 1;
z++;
}else if( *z=='+' ){
z++;
@@ -789,8 +791,8 @@ int sqlite3AtoF(const char *z, double *pResult){
/* if exponent is present */
if( *z=='e' || *z=='E' ){
int esign = 1; /* sign of exponent */
z++;
eValid = 0;
eType++;
/* get sign of exponent */
@@ -801,10 +803,16 @@ int sqlite3AtoF(const char *z, double *pResult){
z++;
}
/* copy digits to exponent */
while( sqlite3Isdigit(*z) ){
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
if( sqlite3Isdigit(*z) ){
int exp = *z - '0';
z++;
eValid = 1;
while( sqlite3Isdigit(*z) ){
exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000;
z++;
}
d += esign*exp;
}else{
eType = -1;
}
}
@@ -813,22 +821,17 @@ int sqlite3AtoF(const char *z, double *pResult){
/* Zero is a special case */
if( s==0 ){
*pResult = sign<0 ? -0.0 : +0.0;
goto atofz_return;
*pResult = neg ? -0.0 : +0.0;
}else{
*pResult = sqlite3Fp10Convert2(s,d);
if( neg ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
}
/* adjust exponent by d, and update sign */
e = (e*esign) + d;
*pResult = sqlite3Fp10Convert2(s,e);
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
atofz_return:
/* return true if number and no extra non-whitespace characters after */
if( z[0]==0 && nDigit>0 && eValid ){
if( z[0]==0 && nDigit>0 ){
return eType;
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
}else if( eType>=2 && nDigit>0 ){
return -1;
}else{
return 0;
@@ -841,7 +844,25 @@ atofz_return:
#pragma warning(default : 4756)
#endif
/*
** Digit pairs used to convert a U64 or I64 into text, two digits
** at a time.
*/
static const union {
char a[201];
short int forceAlignment;
} sqlite3DigitPairs = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
/*
@@ -855,23 +876,35 @@ atofz_return:
int sqlite3Int64ToText(i64 v, char *zOut){
int i;
u64 x;
char zTemp[22];
if( v<0 ){
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}else{
union {
char a[23];
u16 forceAlignment;
} u;
if( v>0 ){
x = v;
}else if( v==0 ){
zOut[0] = '0';
zOut[1] = 0;
return 1;
}else{
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}
i = sizeof(zTemp)-2;
zTemp[sizeof(zTemp)-1] = 0;
while( 1 /*exit-by-break*/ ){
zTemp[i] = (x%10) + '0';
x = x/10;
if( x==0 ) break;
i--;
};
if( v<0 ) zTemp[--i] = '-';
memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
return sizeof(zTemp)-1-i;
i = sizeof(u.a)-1;
u.a[i] = 0;
while( x>=10 ){
int kk = (x%100)*2;
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
*(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
x /= 100;
}
if( x ){
u.a[--i] = x + '0';
}
if( v<0 ) u.a[--i] = '-';
memcpy(zOut, &u.a[i], sizeof(u.a)-i);
return sizeof(u.a)-1-i;
}
/*
@@ -1128,7 +1161,7 @@ int sqlite3Atoi(const char *z){
** representation.
**
** If iRound<=0 then round to -iRound significant digits to the
** the left of the decimal point, or to a maximum of mxRound total
** the right of the decimal point, or to a maximum of mxRound total
** significant digits.
**
** If iRound>0 round to min(iRound,mxRound) significant digits total.
@@ -1141,12 +1174,14 @@ int sqlite3Atoi(const char *z){
** The p->z[] array is *not* zero-terminated.
*/
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
int i;
u64 v;
int e, exp = 0;
int i; /* Index into zBuf[] where to put next character */
int n; /* Number of digits */
u64 v; /* mantissa */
int e, exp = 0; /* Base-2 and base-10 exponent */
char *zBuf; /* Local alias for p->zBuf */
char *z; /* Local alias for p->z */
p->isSpecial = 0;
p->z = p->zBuf;
assert( mxRound>0 );
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
@@ -1169,67 +1204,89 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
p->n = 0;
p->iDP = 0;
p->z = p->zBuf;
return;
}
v &= 0x000fffffffffffffULL;
if( e==0 ){
int n = countLeadingZeros(v);
v <<= n;
e = -1074 - n;
int nn = countLeadingZeros(v);
v <<= nn;
e = -1074 - nn;
}else{
v = (v<<11) | U64_BIT(63);
e -= 1086;
}
sqlite3Fp2Convert10(v, e, 17, &v, &exp);
sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp);
/* Extract significant digits. */
/* Extract significant digits, start at the right-most slot in p->zBuf
** and working back to the right. "i" keeps track of the next slot in
** which to store a digit. */
i = sizeof(p->zBuf)-1;
zBuf = p->zBuf;
assert( v>0 );
while( v>=10 ){
static const union {
char a[200];
short int forAlignment;
} dig = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
int kk = (v%100)*2;
assert( TWO_BYTE_ALIGNMENT(&dig.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&p->zBuf[i-1]) );
*(u16*)(&p->zBuf[i-1]) = *(u16*)&dig.a[kk];
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) );
*(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
v /= 100;
}
if( v ){
assert( v<10 );
p->zBuf[i--] = v + '0';
zBuf[i--] = v + '0';
}
assert( i>=0 && i<sizeof(p->zBuf)-1 );
p->n = sizeof(p->zBuf) - 1 - i;
assert( p->n>0 );
assert( p->n<sizeof(p->zBuf) );
p->iDP = p->n + exp;
n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */
assert( n>0 );
assert( n<sizeof(p->zBuf) );
testcase( n==sizeof(p->zBuf)-1 );
p->iDP = n + exp;
if( iRound<=0 ){
iRound = p->iDP - iRound;
if( iRound==0 && p->zBuf[i+1]>='5' ){
if( iRound==0 && zBuf[i+1]>='5' ){
iRound = 1;
p->zBuf[i--] = '0';
p->n++;
zBuf[i--] = '0';
n++;
p->iDP++;
}
}
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
char *z = &p->zBuf[i+1];
z = &zBuf[i+1]; /* z points to the first digit */
if( iRound>0 && (iRound<n || n>mxRound) ){
if( iRound>mxRound ) iRound = mxRound;
p->n = iRound;
if( iRound==17 ){
/* If the precision is exactly 17, which only happens with the "!"
** flag (ex: "%!.17g") then try to reduce the precision if that
** yields text that will round-trip to the original floating-point.
** value. Thus, for exaple, 49.47 will render as 49.47, rather than
** as 49.469999999999999. */
if( z[15]=='9' && z[14]=='9' ){
int jj, kk;
u64 v2;
for(jj=14; jj>0 && z[jj-1]=='9'; jj--){}
if( jj==0 ){
v2 = 1;
}else{
v2 = z[0] - '0';
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
v2++;
}
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
iRound = jj+1;
}
}else if( p->iDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){
int jj, kk;
u64 v2;
assert( z[0]!='0' );
for(jj=14; z[jj-1]=='0'; jj--){}
v2 = z[0] - '0';
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
iRound = jj+1;
}
}
}
n = iRound;
if( z[iRound]>='5' ){
int j = iRound-1;
while( 1 /*exit-by-break*/ ){
@@ -1237,8 +1294,9 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
if( z[j]<='9' ) break;
z[j] = '0';
if( j==0 ){
p->z[i--] = '1';
p->n++;
z--;
z[0] = '1';
n++;
p->iDP++;
break;
}else{
@@ -1247,13 +1305,13 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
}
}
}
p->z = &p->zBuf[i+1];
assert( i+p->n < sizeof(p->zBuf) );
assert( p->n>0 );
while( p->z[p->n-1]=='0' ){
p->n--;
assert( p->n>0 );
assert( n>0 );
while( z[n-1]=='0' ){
n--;
assert( n>0 );
}
p->n = n;
p->z = z;
}
/*
+10 -5
View File
@@ -107,10 +107,11 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
StrAccum acc;
assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
assert( sz>22 );
if( p->flags & MEM_Int ){
#if GCC_VERSION>=7000000
if( p->flags & (MEM_Int|MEM_IntReal) ){
#if 0
/* Work-around for GCC bug
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270.
** Bug fixed circa 2020, so this work-around removed in 2026. */
i64 x;
assert( (p->flags&MEM_Int)*2==sizeof(x) );
memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
@@ -118,10 +119,14 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
#else
p->n = sqlite3Int64ToText(p->u.i, zBuf);
#endif
if( p->flags & MEM_IntReal ){
memcpy(zBuf+p->n,".0", 3);
p->n += 2;
}
}else{
sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
sqlite3_str_appendf(&acc, "%!.15g",
(p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
sqlite3_str_appendf(&acc, "%!.*g",
(p->db ? p->db->nFpDigit : 17), p->u.r);
assert( acc.zText==zBuf && acc.mxAlloc<=0 );
zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
p->n = acc.nChar;
+35
View File
@@ -0,0 +1,35 @@
# 2026-02-20
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests of the sqlite3AtoF() function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Rounding cases:
#
do_execsql_test atof2-1.0 {
SELECT format('%g',192.496475);
} 192.496
do_execsql_test atof2-1.1 {
SELECT format('%g',192.496501);
} 192.497
load_static_extension db ieee754
do_execsql_test atof2-2.1 {
SELECT format('%!.30f',ieee754_inc(100.0,-1));
} 99.9999999999999858
do_execsql_test atof2-2.2 {
SELECT format('%!.30f',ieee754_inc(100.0,-2));
} 99.9999999999999716
finish_test
+4 -4
View File
@@ -1744,10 +1744,10 @@ do_execsql_test e_expr-32.2.8 {
integer 9223372036854775807 \
integer 9223372036854775807 \
integer 9223372036854775807 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
integer -5 \
integer -5 \
]
+60 -6
View File
@@ -17,28 +17,82 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Unusual rendering cases:
#
do_execsql_test fpconv1-1.0 {
SELECT 1.23 - 2.34;
} {-1.1099999999999999}
# ^--- Not -1.11 as you would expect. -1.11 has a different bit pattern
do_execsql_test fpconv1-1.1 {
SELECT 1.23 * 2.34;
} {2.8781999999999996}
# ^--- Not 2.8782 as you would expect. 2.8782 has a different bit pattern
# Change significant digits to 15 and get a different result.
sqlite3_db_config db FP_DIGITS 15
do_execsql_test fpconv1-1.2 {
SELECT 1.23 - 2.34;
} {-1.11}
do_execsql_test fpconv1-1.3 {
SELECT 1.23 * 2.34;
} {2.8782}
sqlite3_db_config db FP_DIGITS 17
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 {
do_execsql_test fpconv1-2.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),
** On a circa 2021 Ryzen 5950X running Mint Linux, and
** compiled with -O0 -DSQLITE_DEBUG, this test runs at
** about 150000 cases per second ------------------vvvvvvv */
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<500_000),
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;
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<17.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.
# that fail to preserve at least 16 significant digits of accuracy.
########################################################################
# Random test to ensure that double -> text -> double conversions
# round-trip exactly.
#
load_static_extension db ieee754
do_execsql_test fpconv1-3.0 {
WITH RECURSIVE
c(x,s) AS MATERIALIZED (VALUES(1,random()&0xffefffffffffffff)
UNION ALL
SELECT x+1,random()&0xffefffffffffffff
FROM c WHERE x<1_000_000),
fp(y,s) AS (
SELECT ieee754_from_int(s),s FROM c
),
fp2(yt,y,s) AS (
SELECT y||'', y, s FROM fp
)
SELECT format('%#016x',s) aS 'orig-hex',
format('%#016x',ieee754_to_int(CAST(yt AS real))) AS 'full-roundtrip',
yt AS 'rendered-as',
decimal_exp(yt,30) AS 'text-decimal',
decimal_exp(ieee754_from_int(s),30) AS 'float-decimal'
FROM fp2
WHERE ieee754_to_int(CAST(yt AS real))<>s;
} {}
# ^---- Values that fail to round-trip will be reported
finish_test
+22
View File
@@ -146,5 +146,27 @@ do_catchsql_test 6.5 {
(SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6);
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.6 {
SELECT *, NOT EXISTS (
SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
) FROM t5;
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.7 {
SELECT *, NOT EXISTS (
SELECT 1
EXCEPT
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
) FROM t5;
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.8 {
SELECT *, NOT EXISTS (
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
EXCEPT
SELECT 1
) FROM t5;
} {1 {ON clause references tables to its right}}
finish_test