diff --git a/manifest b/manifest index 986addf1fe..a3dc17de19 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Instead\sof\sallocating\sa\ssingle\slarge\sbuffer\sat\sthe\sbeginning\sof\seach\ssort\soperation,\sstart\swith\sa\ssmall\sbuffer\sand\sextend\sit\susing\srealloc()\sas\srequired. -D 2014-03-27T19:25:02.222 +C Merge\sthe\slatest\schanges\sfrom\strunk. +D 2014-03-28T18:35:39.779 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,7 +164,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 8d7e432bdd27d63182865c708ea0e7606489b6d1 +F src/btree.c a59a199f21338ae1847d69f5db87c3e8ef1b1578 F src/btree.h 232836cb51753f2e96aa8ce0f052c6df850f76ba F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 @@ -222,7 +222,7 @@ F src/shell.c cee9f46f2688a261601b1fd3d7f4b3cddf9b5cdf F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h afbf39e96736ceb85e1d896b281ba2406dd70aa0 +F src/sqliteInt.h cc9582a91b2910404ccda7b7e198815ea0f75948 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -279,10 +279,10 @@ F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 02f2de0b2f3b198438e3e64a2ceba9407bb8348b -F src/vdbe.h fb2c48c198300a7c632f09fc940011d2ad2fc2ae -F src/vdbeInt.h 2b9a6849166d0014c843ae3fd83a062be4efa325 +F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94 +F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7 F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4 -F src/vdbeaux.c f81ef920dcf76aceaa1ce77081e9fc5d7a0993dd +F src/vdbeaux.c 1153175fb57a8454e1c8cf79b59b7bf92b26779d F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447 F src/vdbesort.c 08d5e1ee199599d9571942f0560f84963c7a1a9b @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c da8ec216f14af617505799b0b4e52c73dda7a5ca +F src/where.c 7d539cedb1c6a6d6b5d2075b8fea3a48db4838eb F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -403,9 +403,9 @@ F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 -F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d +F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804 F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb -F test/corruptI.test 1b796461e5b635e0a74e3c4ecb1121c82d319dff +F test/corruptI.test b3e4203d420490fc3d3062711597bc1dea06a789 F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f @@ -1056,7 +1056,7 @@ F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e -F test/wal64k.test 63828c2161ad76ddd4109dee0a096b6ef6895698 +F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 @@ -1121,7 +1121,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc -F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75 +F tool/logest.c 388c318c7ac8b52b7c08ca1e2de0f4ca9a8f7e81 F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383 F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1159,7 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P f4ac1bf28c4ba395ccab8f1c9df72614a61095a7 -R 5fefa7763a5f0d580046ba5219de21a5 -U dan -Z 8f7301353335dd4530b24cac1ad9c37a +P 81987c8ceb64f051528a6ca42673821d9ab7c0ff 27deb6e49bcc76714dbdc61b34748603155ac770 +R 79fcad4572db3d584834fdf0de4170a6 +U drh +Z 871d90dec169e4d494b7ff32475fff97 diff --git a/manifest.uuid b/manifest.uuid index cf2496b0b2..518ac58c2a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -81987c8ceb64f051528a6ca42673821d9ab7c0ff \ No newline at end of file +3047a25f1c41e83f0b4772f7c36fbfec0f12dc7e \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 43d41d67e9..c3055836c9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4588,6 +4588,7 @@ int sqlite3BtreeMovetoUnpacked( if( pIdxKey ){ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); + pIdxKey->isCorrupt = 0; assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1 @@ -4711,6 +4712,7 @@ int sqlite3BtreeMovetoUnpacked( c = xRecordCompare(nCell, pCellKey, pIdxKey, 0); sqlite3_free(pCellKey); } + assert( pIdxKey->isCorrupt==0 || c==0 ); if( c<0 ){ lwr = idx+1; }else if( c>0 ){ @@ -4720,6 +4722,7 @@ int sqlite3BtreeMovetoUnpacked( *pRes = 0; rc = SQLITE_OK; pCur->aiIdx[pCur->iPage] = (u16)idx; + if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT; goto moveto_finish; } if( lwr>upr ) break; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5e0dd91ec9..0f67748fc8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1627,6 +1627,7 @@ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ + u8 isCorrupt; /* Corruption detected by xRecordCompare() */ Mem *aMem; /* Values */ int r1; /* Value to return if (lhs > rhs) */ int r2; /* Value to return if (rhs < lhs) */ diff --git a/src/vdbe.h b/src/vdbe.h index 8e300b88a6..10a4140ee1 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -211,10 +211,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int); #endif void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int); +int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); -typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int); +typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int); RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b752478035..043b56da59 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -392,7 +392,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*); +int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeExec(Vdbe*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index f5e4b0a9fc..0ce21378d5 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3405,10 +3405,13 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ ** Key1 and Key2 do not have to contain the same number of fields. If all ** fields that appear in both keys are equal, then pPKey2->default_rc is ** returned. +** +** If database corruption is discovered, set pPKey2->isCorrupt to non-zero +** and return 0. */ int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ - const UnpackedRecord *pPKey2, /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ ){ u32 d1; /* Offset into aKey[] of next data element */ @@ -3434,7 +3437,10 @@ int sqlite3VdbeRecordCompare( }else{ idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; - if( d1>(unsigned)nKey1 ) return 1; /* Corruption */ + if( d1>(unsigned)nKey1 ){ + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + } i = 0; } @@ -3511,7 +3517,8 @@ int sqlite3VdbeRecordCompare( testcase( (d1+mem1.n)==(unsigned)nKey1 ); testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); if( (d1+mem1.n) > (unsigned)nKey1 ){ - rc = 1; /* Corruption */ + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ }else if( pKeyInfo->aColl[i] ){ mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; @@ -3537,7 +3544,8 @@ int sqlite3VdbeRecordCompare( testcase( (d1+nStr)==(unsigned)nKey1 ); testcase( (d1+nStr+1)==(unsigned)nKey1 ); if( (d1+nStr) > (unsigned)nKey1 ){ - rc = 1; /* Corruption */ + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ }else{ int nCmp = MIN(nStr, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); @@ -3596,7 +3604,7 @@ int sqlite3VdbeRecordCompare( */ static int vdbeRecordCompareInt( int nKey1, const void *pKey1, /* Left key */ - const UnpackedRecord *pPKey2, /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ int bSkip /* Ignored */ ){ const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; @@ -3694,7 +3702,7 @@ static int vdbeRecordCompareInt( */ static int vdbeRecordCompareString( int nKey1, const void *pKey1, /* Left key */ - const UnpackedRecord *pPKey2, /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ int bSkip ){ const u8 *aKey1 = (const u8*)pKey1; @@ -3715,7 +3723,10 @@ static int vdbeRecordCompareString( int szHdr = aKey1[0]; nStr = (serial_type-12) / 2; - if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ + if( (szHdr + nStr) > nKey1 ){ + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + } nCmp = MIN( pPKey2->aMem[0].n, nStr ); res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); @@ -3880,7 +3891,7 @@ idx_rowid_corruption: */ int sqlite3VdbeIdxKeyCompare( VdbeCursor *pC, /* The cursor to compare against */ - const UnpackedRecord *pUnpacked, /* Unpacked version of key */ + UnpackedRecord *pUnpacked, /* Unpacked version of key */ int *res /* Write the comparison result here */ ){ i64 nCellKey = 0; diff --git a/src/where.c b/src/where.c index 15084f099a..93ee8c59c3 100644 --- a/src/where.c +++ b/src/where.c @@ -4328,18 +4328,34 @@ static int whereLoopAddBtree( ) ){ pNew->iSortIdx = b ? iSortIdx : 0; + /* TUNING: The base cost of an index scan is N + log2(N). + ** The log2(N) is for the initial seek to the beginning and the N + ** is for the scan itself. */ + pNew->rRun = sqlite3LogEstAdd(rSize, rLogSize); if( m==0 ){ /* TUNING: Cost of a covering index scan is K*(N + log2(N)). ** + The extra factor K of between 1.1 and 3.0 that depends ** on the relative sizes of the table and the index. K ** is smaller for smaller indices, thus favoring them. + ** The upper bound on K (3.0) matches the penalty factor + ** on a full table scan that tries to encourage the use of + ** indexed lookups over full scans. */ - pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 + - (15*pProbe->szIdxRow)/pTab->szTabRow; + pNew->rRun += 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; }else{ - /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) - ** which we will simplify to just N*log2(N) */ - pNew->rRun = rSize + rLogSize; + /* TUNING: The cost of scanning a non-covering index is multiplied + ** by log2(N) to account for the binary search of the main table + ** that must happen for each row of the index. + ** TODO: Should there be a multiplier here, analogous to the 3x + ** multiplier for a fulltable scan or covering index scan, to + ** further discourage the use of an index scan? Or is the log2(N) + ** term sufficient discouragement? + ** TODO: What if some or all of the WHERE clause terms can be + ** computed without reference to the original table. Then the + ** penality should reduce to logK where K is the number of output + ** rows. + */ + pNew->rRun += rLogSize; } whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); @@ -4920,7 +4936,7 @@ static i8 wherePathSatisfiesOrderBy( } } } /* End the loop over all WhereLoops from outer-most down to inner-most */ - if( obSat==obDone ) return nOrderBy; + if( obSat==obDone ) return (i8)nOrderBy; if( !isOrderDistinct ){ for(i=nOrderBy-1; i>0; i--){ Bitmask m = MASKBIT(i) - 1; @@ -5041,11 +5057,19 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, iLoop, pWLoop, &revMask); if( isOrdered>=0 && isOrdered0 ); + rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66; + rSortCost = nRowEst + estLog(nRowEst) + rScale; /* TUNING: The cost of implementing DISTINCT using a B-TREE is ** also N*log(N) but it has a larger constant of proportionality. ** Multiply by 3.0. */ diff --git a/test/corruptG.test b/test/corruptG.test index 1ec5d6f6a9..af920edf41 100644 --- a/test/corruptG.test +++ b/test/corruptG.test @@ -47,12 +47,12 @@ do_test 1.2 { catchsql { SELECT c FROM t1 WHERE a>'abc'; } -} {0 {}} +} {1 {database disk image is malformed}} do_test 1.3 { catchsql { PRAGMA integrity_check } -} {0 ok} +} {1 {database disk image is malformed}} do_test 1.4 { catchsql { SELECT c FROM t1 ORDER BY a; @@ -71,11 +71,6 @@ do_test 2.1 { catchsql { SELECT rowid FROM t1 WHERE a='abc' and b='xyz123456789XYZ'; } - # The following test result is brittle. The point above is to try to - # force a buffer overread by a corrupt database file. If we get an - # incorrect answer from a corrupt database file, that is OK. If the - # result below changes, that just means that "undefined behavior" has - # changed. -} {/0 .*/} +} {1 {database disk image is malformed}} finish_test diff --git a/test/corruptI.test b/test/corruptI.test index 087a0f3b01..ed34c0f8c3 100644 --- a/test/corruptI.test +++ b/test/corruptI.test @@ -51,7 +51,7 @@ do_test 1.3 { hexio_write test.db $off FFFF7f02 sqlite3 db test.db catchsql { SELECT * FROM t1 WHERE a = 10 } -} {0 {}} +} {1 {database disk image is malformed}} do_test 2.0 { execsql { diff --git a/test/wal64k.test b/test/wal64k.test index afd820778e..e962da128e 100644 --- a/test/wal64k.test +++ b/test/wal64k.test @@ -19,6 +19,11 @@ set testprefix wal64k ifcapable !wal {finish_test ; return } +if {$tcl_platform(platform) != "unix"} { + finish_test + return +} + db close test_syscall pagesize 65536 sqlite3 db test.db @@ -44,4 +49,3 @@ integrity_check 1.3 db close test_syscall pagesize -1 finish_test - diff --git a/tool/logest.c b/tool/logest.c index 8dad6cc9b6..1ac337d36c 100644 --- a/tool/logest.c +++ b/tool/logest.c @@ -17,13 +17,7 @@ ** ** ./LogEst ARGS ** -** Arguments: -** -** 'x' Multiple the top two elements of the stack -** '+' Add the top two elements of the stack -** NUM Convert NUM from integer to LogEst and push onto the stack -** ^NUM Interpret NUM as a LogEst and push onto stack. -** +** See the showHelp() routine for a description of valid arguments. ** Examples: ** ** To convert 123 from LogEst to integer: @@ -97,12 +91,31 @@ static LogEst logEstFromDouble(double x){ return e*10; } +int isInteger(const char *z){ + while( z[0]>='0' && z[0]<='9' ) z++; + return z[0]==0; +} + int isFloat(const char *z){ - while( z[0] ){ - if( z[0]=='.' || z[0]=='E' || z[0]=='e' ) return 1; - z++; - } - return 0; + char c; + while( ((c=z[0])>='0' && c<='9') || c=='.' || c=='E' || c=='e' + || c=='+' || c=='-' ) z++; + return z[0]==0; +} + +static void showHelp(const char *zArgv0){ + printf("Usage: %s ARGS...\n", zArgv0); + printf("Arguments:\n" + " NUM Convert NUM from integer to LogEst and push onto the stack\n" + " ^NUM Interpret NUM as a LogEst and push onto stack\n" + " x Multiple the top two elements of the stack\n" + " + Add the top two elements of the stack\n" + " dup Dupliate the top element on the stack\n" + " inv Take the reciprocal of the top of stack. N = 1/N.\n" + " log Find the LogEst of the number on top of stack\n" + " nlogn Compute NlogN where N is the top of stack\n" + ); + exit(1); } int main(int argc, char **argv){ @@ -111,30 +124,43 @@ int main(int argc, char **argv){ LogEst a[100]; for(i=1; i=2 ){ a[n-2] = logEstAdd(a[n-2],a[n-1]); n--; } - }else if( z[0]=='x' ){ + }else if( strcmp(z,"x")==0 ){ if( n>=2 ){ a[n-2] = logEstMultiply(a[n-2],a[n-1]); n--; } + }else if( strcmp(z,"dup")==0 ){ + if( n>0 ){ + a[n] = a[n-1]; + n++; + } + }else if( strcmp(z,"log")==0 ){ + if( n>0 ) a[n-1] = logEstFromInteger(a[n-1]) - 33; + }else if( strcmp(z,"nlogn")==0 ){ + if( n>0 ) a[n-1] += logEstFromInteger(a[n-1]) - 33; + }else if( strcmp(z,"inv")==0 ){ + if( n>0 ) a[n-1] = -a[n-1]; }else if( z[0]=='^' ){ a[n++] = atoi(z+1); - }else if( isFloat(z) ){ + }else if( isInteger(z) ){ + a[n++] = logEstFromInteger(atoi(z)); + }else if( isFloat(z) && z[0]!='-' ){ a[n++] = logEstFromDouble(atof(z)); }else{ - a[n++] = logEstFromInteger(atoi(z)); + showHelp(argv[0]); } } for(i=n-1; i>=0; i--){ if( a[i]<0 ){ - printf("%d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i])); + printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i])); }else{ sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024; - printf("%d (%lld.%02lld)\n", a[i], x/100, x%100); + printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100); } } return 0;