| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 ** A program for performance testing. | |
| 3 ** | |
| 4 ** The available command-line options are described below: | |
| 5 */ | |
| 6 static const char zHelp[] = | |
| 7 "Usage: %s [--options] DATABASE\n" | |
| 8 "Options:\n" | |
| 9 " --autovacuum Enable AUTOVACUUM mode\n" | |
| 10 " --cachesize N Set the cache size to N\n" | |
| 11 " --exclusive Enable locking_mode=EXCLUSIVE\n" | |
| 12 " --explain Like --sqlonly but with added EXPLAIN keywords\n" | |
| 13 " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" | |
| 14 " --incrvacuum Enable incremenatal vacuum mode\n" | |
| 15 " --journal M Set the journal_mode to M\n" | |
| 16 " --key KEY Set the encryption key to KEY\n" | |
| 17 " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" | |
| 18 " --multithread Set multithreaded mode\n" | |
| 19 " --nomemstat Disable memory statistics\n" | |
| 20 " --nosync Set PRAGMA synchronous=OFF\n" | |
| 21 " --notnull Add NOT NULL constraints to table columns\n" | |
| 22 " --pagesize N Set the page size to N\n" | |
| 23 " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" | |
| 24 " --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n" | |
| 25 " --reprepare Reprepare each statement upon every invocation\n" | |
| 26 " --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n
" | |
| 27 " --serialized Set serialized threading mode\n" | |
| 28 " --singlethread Set single-threaded mode - disables all mutexing\n" | |
| 29 " --sqlonly No-op. Only show the SQL that would have been run.\n" | |
| 30 " --shrink-memory Invoke sqlite3_db_release_memory() frequently.\n" | |
| 31 " --size N Relative test size. Default=100\n" | |
| 32 " --stats Show statistics at the end\n" | |
| 33 " --testset T Run test-set T\n" | |
| 34 " --trace Turn on SQL tracing\n" | |
| 35 " --threads N Use up to N threads for sorting\n" | |
| 36 " --utf16be Set text encoding to UTF-16BE\n" | |
| 37 " --utf16le Set text encoding to UTF-16LE\n" | |
| 38 " --verify Run additional verification steps.\n" | |
| 39 " --without-rowid Use WITHOUT ROWID where appropriate\n" | |
| 40 ; | |
| 41 | |
| 42 | |
| 43 #include "sqlite3.h" | |
| 44 #include <assert.h> | |
| 45 #include <stdio.h> | |
| 46 #include <stdlib.h> | |
| 47 #include <stdarg.h> | |
| 48 #include <string.h> | |
| 49 #include <ctype.h> | |
| 50 #define ISSPACE(X) isspace((unsigned char)(X)) | |
| 51 #define ISDIGIT(X) isdigit((unsigned char)(X)) | |
| 52 | |
| 53 #if SQLITE_VERSION_NUMBER<3005000 | |
| 54 # define sqlite3_int64 sqlite_int64 | |
| 55 #endif | |
| 56 #ifdef SQLITE_ENABLE_RBU | |
| 57 # include "sqlite3rbu.h" | |
| 58 #endif | |
| 59 | |
| 60 /* All global state is held in this structure */ | |
| 61 static struct Global { | |
| 62 sqlite3 *db; /* The open database connection */ | |
| 63 sqlite3_stmt *pStmt; /* Current SQL statement */ | |
| 64 sqlite3_int64 iStart; /* Start-time for the current test */ | |
| 65 sqlite3_int64 iTotal; /* Total time */ | |
| 66 int bWithoutRowid; /* True for --without-rowid */ | |
| 67 int bReprepare; /* True to reprepare the SQL on each rerun */ | |
| 68 int bSqlOnly; /* True to print the SQL once only */ | |
| 69 int bExplain; /* Print SQL with EXPLAIN prefix */ | |
| 70 int bVerify; /* Try to verify that results are correct */ | |
| 71 int bMemShrink; /* Call sqlite3_db_release_memory() often */ | |
| 72 int szTest; /* Scale factor for test iterations */ | |
| 73 const char *zWR; /* Might be WITHOUT ROWID */ | |
| 74 const char *zNN; /* Might be NOT NULL */ | |
| 75 const char *zPK; /* Might be UNIQUE or PRIMARY KEY */ | |
| 76 unsigned int x, y; /* Pseudo-random number generator state */ | |
| 77 int nResult; /* Size of the current result */ | |
| 78 char zResult[3000]; /* Text of the current result */ | |
| 79 } g; | |
| 80 | |
| 81 | |
| 82 /* Print an error message and exit */ | |
| 83 static void fatal_error(const char *zMsg, ...){ | |
| 84 va_list ap; | |
| 85 va_start(ap, zMsg); | |
| 86 vfprintf(stderr, zMsg, ap); | |
| 87 va_end(ap); | |
| 88 exit(1); | |
| 89 } | |
| 90 | |
| 91 /* | |
| 92 ** Return the value of a hexadecimal digit. Return -1 if the input | |
| 93 ** is not a hex digit. | |
| 94 */ | |
| 95 static int hexDigitValue(char c){ | |
| 96 if( c>='0' && c<='9' ) return c - '0'; | |
| 97 if( c>='a' && c<='f' ) return c - 'a' + 10; | |
| 98 if( c>='A' && c<='F' ) return c - 'A' + 10; | |
| 99 return -1; | |
| 100 } | |
| 101 | |
| 102 /* Provide an alternative to sqlite3_stricmp() in older versions of | |
| 103 ** SQLite */ | |
| 104 #if SQLITE_VERSION_NUMBER<3007011 | |
| 105 # define sqlite3_stricmp strcmp | |
| 106 #endif | |
| 107 | |
| 108 /* | |
| 109 ** Interpret zArg as an integer value, possibly with suffixes. | |
| 110 */ | |
| 111 static int integerValue(const char *zArg){ | |
| 112 sqlite3_int64 v = 0; | |
| 113 static const struct { char *zSuffix; int iMult; } aMult[] = { | |
| 114 { "KiB", 1024 }, | |
| 115 { "MiB", 1024*1024 }, | |
| 116 { "GiB", 1024*1024*1024 }, | |
| 117 { "KB", 1000 }, | |
| 118 { "MB", 1000000 }, | |
| 119 { "GB", 1000000000 }, | |
| 120 { "K", 1000 }, | |
| 121 { "M", 1000000 }, | |
| 122 { "G", 1000000000 }, | |
| 123 }; | |
| 124 int i; | |
| 125 int isNeg = 0; | |
| 126 if( zArg[0]=='-' ){ | |
| 127 isNeg = 1; | |
| 128 zArg++; | |
| 129 }else if( zArg[0]=='+' ){ | |
| 130 zArg++; | |
| 131 } | |
| 132 if( zArg[0]=='0' && zArg[1]=='x' ){ | |
| 133 int x; | |
| 134 zArg += 2; | |
| 135 while( (x = hexDigitValue(zArg[0]))>=0 ){ | |
| 136 v = (v<<4) + x; | |
| 137 zArg++; | |
| 138 } | |
| 139 }else{ | |
| 140 while( isdigit(zArg[0]) ){ | |
| 141 v = v*10 + zArg[0] - '0'; | |
| 142 zArg++; | |
| 143 } | |
| 144 } | |
| 145 for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ | |
| 146 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ | |
| 147 v *= aMult[i].iMult; | |
| 148 break; | |
| 149 } | |
| 150 } | |
| 151 if( v>0x7fffffff ) fatal_error("parameter too large - max 2147483648"); | |
| 152 return (int)(isNeg? -v : v); | |
| 153 } | |
| 154 | |
| 155 /* Return the current wall-clock time, in milliseconds */ | |
| 156 sqlite3_int64 speedtest1_timestamp(void){ | |
| 157 #if SQLITE_VERSION_NUMBER<3005000 | |
| 158 return 0; | |
| 159 #else | |
| 160 static sqlite3_vfs *clockVfs = 0; | |
| 161 sqlite3_int64 t; | |
| 162 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); | |
| 163 #if SQLITE_VERSION_NUMBER>=3007000 | |
| 164 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ | |
| 165 clockVfs->xCurrentTimeInt64(clockVfs, &t); | |
| 166 }else | |
| 167 #endif | |
| 168 { | |
| 169 double r; | |
| 170 clockVfs->xCurrentTime(clockVfs, &r); | |
| 171 t = (sqlite3_int64)(r*86400000.0); | |
| 172 } | |
| 173 return t; | |
| 174 #endif | |
| 175 } | |
| 176 | |
| 177 /* Return a pseudo-random unsigned integer */ | |
| 178 unsigned int speedtest1_random(void){ | |
| 179 g.x = (g.x>>1) ^ ((1+~(g.x&1)) & 0xd0000001); | |
| 180 g.y = g.y*1103515245 + 12345; | |
| 181 return g.x ^ g.y; | |
| 182 } | |
| 183 | |
| 184 /* Map the value in within the range of 1...limit into another | |
| 185 ** number in a way that is chatic and invertable. | |
| 186 */ | |
| 187 unsigned swizzle(unsigned in, unsigned limit){ | |
| 188 unsigned out = 0; | |
| 189 while( limit ){ | |
| 190 out = (out<<1) | (in&1); | |
| 191 in >>= 1; | |
| 192 limit >>= 1; | |
| 193 } | |
| 194 return out; | |
| 195 } | |
| 196 | |
| 197 /* Round up a number so that it is a power of two minus one | |
| 198 */ | |
| 199 unsigned roundup_allones(unsigned limit){ | |
| 200 unsigned m = 1; | |
| 201 while( m<limit ) m = (m<<1)+1; | |
| 202 return m; | |
| 203 } | |
| 204 | |
| 205 /* The speedtest1_numbername procedure below converts its argment (an integer) | |
| 206 ** into a string which is the English-language name for that number. | |
| 207 ** The returned string should be freed with sqlite3_free(). | |
| 208 ** | |
| 209 ** Example: | |
| 210 ** | |
| 211 ** speedtest1_numbername(123) -> "one hundred twenty three" | |
| 212 */ | |
| 213 int speedtest1_numbername(unsigned int n, char *zOut, int nOut){ | |
| 214 static const char *ones[] = { "zero", "one", "two", "three", "four", "five", | |
| 215 "six", "seven", "eight", "nine", "ten", "eleven", "twelve", | |
| 216 "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", | |
| 217 "eighteen", "nineteen" }; | |
| 218 static const char *tens[] = { "", "ten", "twenty", "thirty", "forty", | |
| 219 "fifty", "sixty", "seventy", "eighty", "ninety" }; | |
| 220 int i = 0; | |
| 221 | |
| 222 if( n>=1000000000 ){ | |
| 223 i += speedtest1_numbername(n/1000000000, zOut+i, nOut-i); | |
| 224 sqlite3_snprintf(nOut-i, zOut+i, " billion"); | |
| 225 i += (int)strlen(zOut+i); | |
| 226 n = n % 1000000000; | |
| 227 } | |
| 228 if( n>=1000000 ){ | |
| 229 if( i && i<nOut-1 ) zOut[i++] = ' '; | |
| 230 i += speedtest1_numbername(n/1000000, zOut+i, nOut-i); | |
| 231 sqlite3_snprintf(nOut-i, zOut+i, " million"); | |
| 232 i += (int)strlen(zOut+i); | |
| 233 n = n % 1000000; | |
| 234 } | |
| 235 if( n>=1000 ){ | |
| 236 if( i && i<nOut-1 ) zOut[i++] = ' '; | |
| 237 i += speedtest1_numbername(n/1000, zOut+i, nOut-i); | |
| 238 sqlite3_snprintf(nOut-i, zOut+i, " thousand"); | |
| 239 i += (int)strlen(zOut+i); | |
| 240 n = n % 1000; | |
| 241 } | |
| 242 if( n>=100 ){ | |
| 243 if( i && i<nOut-1 ) zOut[i++] = ' '; | |
| 244 sqlite3_snprintf(nOut-i, zOut+i, "%s hundred", ones[n/100]); | |
| 245 i += (int)strlen(zOut+i); | |
| 246 n = n % 100; | |
| 247 } | |
| 248 if( n>=20 ){ | |
| 249 if( i && i<nOut-1 ) zOut[i++] = ' '; | |
| 250 sqlite3_snprintf(nOut-i, zOut+i, "%s", tens[n/10]); | |
| 251 i += (int)strlen(zOut+i); | |
| 252 n = n % 10; | |
| 253 } | |
| 254 if( n>0 ){ | |
| 255 if( i && i<nOut-1 ) zOut[i++] = ' '; | |
| 256 sqlite3_snprintf(nOut-i, zOut+i, "%s", ones[n]); | |
| 257 i += (int)strlen(zOut+i); | |
| 258 } | |
| 259 if( i==0 ){ | |
| 260 sqlite3_snprintf(nOut-i, zOut+i, "zero"); | |
| 261 i += (int)strlen(zOut+i); | |
| 262 } | |
| 263 return i; | |
| 264 } | |
| 265 | |
| 266 | |
| 267 /* Start a new test case */ | |
| 268 #define NAMEWIDTH 60 | |
| 269 static const char zDots[] = | |
| 270 "......................................................................."; | |
| 271 void speedtest1_begin_test(int iTestNum, const char *zTestName, ...){ | |
| 272 int n = (int)strlen(zTestName); | |
| 273 char *zName; | |
| 274 va_list ap; | |
| 275 va_start(ap, zTestName); | |
| 276 zName = sqlite3_vmprintf(zTestName, ap); | |
| 277 va_end(ap); | |
| 278 n = (int)strlen(zName); | |
| 279 if( n>NAMEWIDTH ){ | |
| 280 zName[NAMEWIDTH] = 0; | |
| 281 n = NAMEWIDTH; | |
| 282 } | |
| 283 if( g.bSqlOnly ){ | |
| 284 printf("/* %4d - %s%.*s */\n", iTestNum, zName, NAMEWIDTH-n, zDots); | |
| 285 }else{ | |
| 286 printf("%4d - %s%.*s ", iTestNum, zName, NAMEWIDTH-n, zDots); | |
| 287 fflush(stdout); | |
| 288 } | |
| 289 sqlite3_free(zName); | |
| 290 g.nResult = 0; | |
| 291 g.iStart = speedtest1_timestamp(); | |
| 292 g.x = 0xad131d0b; | |
| 293 g.y = 0x44f9eac8; | |
| 294 } | |
| 295 | |
| 296 /* Complete a test case */ | |
| 297 void speedtest1_end_test(void){ | |
| 298 sqlite3_int64 iElapseTime = speedtest1_timestamp() - g.iStart; | |
| 299 if( !g.bSqlOnly ){ | |
| 300 g.iTotal += iElapseTime; | |
| 301 printf("%4d.%03ds\n", (int)(iElapseTime/1000), (int)(iElapseTime%1000)); | |
| 302 } | |
| 303 if( g.pStmt ){ | |
| 304 sqlite3_finalize(g.pStmt); | |
| 305 g.pStmt = 0; | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 /* Report end of testing */ | |
| 310 void speedtest1_final(void){ | |
| 311 if( !g.bSqlOnly ){ | |
| 312 printf(" TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots, | |
| 313 (int)(g.iTotal/1000), (int)(g.iTotal%1000)); | |
| 314 } | |
| 315 } | |
| 316 | |
| 317 /* Print an SQL statement to standard output */ | |
| 318 static void printSql(const char *zSql){ | |
| 319 int n = (int)strlen(zSql); | |
| 320 while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ){ n--; } | |
| 321 if( g.bExplain ) printf("EXPLAIN "); | |
| 322 printf("%.*s;\n", n, zSql); | |
| 323 if( g.bExplain | |
| 324 #if SQLITE_VERSION_NUMBER>=3007017 | |
| 325 && ( sqlite3_strglob("CREATE *", zSql)==0 | |
| 326 || sqlite3_strglob("DROP *", zSql)==0 | |
| 327 || sqlite3_strglob("ALTER *", zSql)==0 | |
| 328 ) | |
| 329 #endif | |
| 330 ){ | |
| 331 printf("%.*s;\n", n, zSql); | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 /* Shrink memory used, if appropriate and if the SQLite version is capable | |
| 336 ** of doing so. | |
| 337 */ | |
| 338 void speedtest1_shrink_memory(void){ | |
| 339 #if SQLITE_VERSION_NUMBER>=3007010 | |
| 340 if( g.bMemShrink ) sqlite3_db_release_memory(g.db); | |
| 341 #endif | |
| 342 } | |
| 343 | |
| 344 /* Run SQL */ | |
| 345 void speedtest1_exec(const char *zFormat, ...){ | |
| 346 va_list ap; | |
| 347 char *zSql; | |
| 348 va_start(ap, zFormat); | |
| 349 zSql = sqlite3_vmprintf(zFormat, ap); | |
| 350 va_end(ap); | |
| 351 if( g.bSqlOnly ){ | |
| 352 printSql(zSql); | |
| 353 }else{ | |
| 354 char *zErrMsg = 0; | |
| 355 int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); | |
| 356 if( zErrMsg ) fatal_error("SQL error: %s\n%s\n", zErrMsg, zSql); | |
| 357 if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db)); | |
| 358 } | |
| 359 sqlite3_free(zSql); | |
| 360 speedtest1_shrink_memory(); | |
| 361 } | |
| 362 | |
| 363 /* Prepare an SQL statement */ | |
| 364 void speedtest1_prepare(const char *zFormat, ...){ | |
| 365 va_list ap; | |
| 366 char *zSql; | |
| 367 va_start(ap, zFormat); | |
| 368 zSql = sqlite3_vmprintf(zFormat, ap); | |
| 369 va_end(ap); | |
| 370 if( g.bSqlOnly ){ | |
| 371 printSql(zSql); | |
| 372 }else{ | |
| 373 int rc; | |
| 374 if( g.pStmt ) sqlite3_finalize(g.pStmt); | |
| 375 rc = sqlite3_prepare_v2(g.db, zSql, -1, &g.pStmt, 0); | |
| 376 if( rc ){ | |
| 377 fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db)); | |
| 378 } | |
| 379 } | |
| 380 sqlite3_free(zSql); | |
| 381 } | |
| 382 | |
| 383 /* Run an SQL statement previously prepared */ | |
| 384 void speedtest1_run(void){ | |
| 385 int i, n, len; | |
| 386 if( g.bSqlOnly ) return; | |
| 387 assert( g.pStmt ); | |
| 388 g.nResult = 0; | |
| 389 while( sqlite3_step(g.pStmt)==SQLITE_ROW ){ | |
| 390 n = sqlite3_column_count(g.pStmt); | |
| 391 for(i=0; i<n; i++){ | |
| 392 const char *z = (const char*)sqlite3_column_text(g.pStmt, i); | |
| 393 if( z==0 ) z = "nil"; | |
| 394 len = (int)strlen(z); | |
| 395 if( g.nResult+len<sizeof(g.zResult)-2 ){ | |
| 396 if( g.nResult>0 ) g.zResult[g.nResult++] = ' '; | |
| 397 memcpy(g.zResult + g.nResult, z, len+1); | |
| 398 g.nResult += len; | |
| 399 } | |
| 400 } | |
| 401 } | |
| 402 #if SQLITE_VERSION_NUMBER>=3006001 | |
| 403 if( g.bReprepare ){ | |
| 404 sqlite3_stmt *pNew; | |
| 405 sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0); | |
| 406 sqlite3_finalize(g.pStmt); | |
| 407 g.pStmt = pNew; | |
| 408 }else | |
| 409 #endif | |
| 410 { | |
| 411 sqlite3_reset(g.pStmt); | |
| 412 } | |
| 413 speedtest1_shrink_memory(); | |
| 414 } | |
| 415 | |
| 416 /* The sqlite3_trace() callback function */ | |
| 417 static void traceCallback(void *NotUsed, const char *zSql){ | |
| 418 int n = (int)strlen(zSql); | |
| 419 while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ) n--; | |
| 420 fprintf(stderr,"%.*s;\n", n, zSql); | |
| 421 } | |
| 422 | |
| 423 /* Substitute random() function that gives the same random | |
| 424 ** sequence on each run, for repeatability. */ | |
| 425 static void randomFunc( | |
| 426 sqlite3_context *context, | |
| 427 int NotUsed, | |
| 428 sqlite3_value **NotUsed2 | |
| 429 ){ | |
| 430 sqlite3_result_int64(context, (sqlite3_int64)speedtest1_random()); | |
| 431 } | |
| 432 | |
| 433 /* Estimate the square root of an integer */ | |
| 434 static int est_square_root(int x){ | |
| 435 int y0 = x/2; | |
| 436 int y1; | |
| 437 int n; | |
| 438 for(n=0; y0>0 && n<10; n++){ | |
| 439 y1 = (y0 + x/y0)/2; | |
| 440 if( y1==y0 ) break; | |
| 441 y0 = y1; | |
| 442 } | |
| 443 return y0; | |
| 444 } | |
| 445 | |
| 446 /* | |
| 447 ** The main and default testset | |
| 448 */ | |
| 449 void testset_main(void){ | |
| 450 int i; /* Loop counter */ | |
| 451 int n; /* iteration count */ | |
| 452 int sz; /* Size of the tables */ | |
| 453 int maxb; /* Maximum swizzled value */ | |
| 454 unsigned x1, x2; /* Parameters */ | |
| 455 int len; /* Length of the zNum[] string */ | |
| 456 char zNum[2000]; /* A number name */ | |
| 457 | |
| 458 sz = n = g.szTest*500; | |
| 459 maxb = roundup_allones(sz); | |
| 460 speedtest1_begin_test(100, "%d INSERTs into table with no index", n); | |
| 461 speedtest1_exec("BEGIN"); | |
| 462 speedtest1_exec("CREATE TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);", | |
| 463 g.zNN, g.zNN, g.zNN); | |
| 464 speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n); | |
| 465 for(i=1; i<=n; i++){ | |
| 466 x1 = swizzle(i,maxb); | |
| 467 speedtest1_numbername(x1, zNum, sizeof(zNum)); | |
| 468 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); | |
| 469 sqlite3_bind_int(g.pStmt, 2, i); | |
| 470 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); | |
| 471 speedtest1_run(); | |
| 472 } | |
| 473 speedtest1_exec("COMMIT"); | |
| 474 speedtest1_end_test(); | |
| 475 | |
| 476 | |
| 477 n = sz; | |
| 478 speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n); | |
| 479 speedtest1_exec("BEGIN"); | |
| 480 speedtest1_exec("CREATE TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s"
, | |
| 481 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); | |
| 482 speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n); | |
| 483 for(i=1; i<=n; i++){ | |
| 484 x1 = swizzle(i,maxb); | |
| 485 speedtest1_numbername(x1, zNum, sizeof(zNum)); | |
| 486 sqlite3_bind_int(g.pStmt, 1, i); | |
| 487 sqlite3_bind_int64(g.pStmt, 2, (sqlite3_int64)x1); | |
| 488 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); | |
| 489 speedtest1_run(); | |
| 490 } | |
| 491 speedtest1_exec("COMMIT"); | |
| 492 speedtest1_end_test(); | |
| 493 | |
| 494 | |
| 495 n = sz; | |
| 496 speedtest1_begin_test(120, "%d unordered INSERTS with one index/PK", n); | |
| 497 speedtest1_exec("BEGIN"); | |
| 498 speedtest1_exec("CREATE TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s"
, | |
| 499 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); | |
| 500 speedtest1_prepare("INSERT INTO t3 VALUES(?1,?2,?3); -- %d times", n); | |
| 501 for(i=1; i<=n; i++){ | |
| 502 x1 = swizzle(i,maxb); | |
| 503 speedtest1_numbername(x1, zNum, sizeof(zNum)); | |
| 504 sqlite3_bind_int(g.pStmt, 2, i); | |
| 505 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); | |
| 506 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); | |
| 507 speedtest1_run(); | |
| 508 } | |
| 509 speedtest1_exec("COMMIT"); | |
| 510 speedtest1_end_test(); | |
| 511 | |
| 512 | |
| 513 n = 25; | |
| 514 speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n); | |
| 515 speedtest1_exec("BEGIN"); | |
| 516 speedtest1_prepare( | |
| 517 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" | |
| 518 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n | |
| 519 ); | |
| 520 for(i=1; i<=n; i++){ | |
| 521 x1 = speedtest1_random()%maxb; | |
| 522 x2 = speedtest1_random()%10 + sz/5000 + x1; | |
| 523 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 524 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 525 speedtest1_run(); | |
| 526 } | |
| 527 speedtest1_exec("COMMIT"); | |
| 528 speedtest1_end_test(); | |
| 529 | |
| 530 | |
| 531 n = 10; | |
| 532 speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n); | |
| 533 speedtest1_exec("BEGIN"); | |
| 534 speedtest1_prepare( | |
| 535 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" | |
| 536 " WHERE c LIKE ?1; -- %d times", n | |
| 537 ); | |
| 538 for(i=1; i<=n; i++){ | |
| 539 x1 = speedtest1_random()%maxb; | |
| 540 zNum[0] = '%'; | |
| 541 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); | |
| 542 zNum[len] = '%'; | |
| 543 zNum[len+1] = 0; | |
| 544 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); | |
| 545 speedtest1_run(); | |
| 546 } | |
| 547 speedtest1_exec("COMMIT"); | |
| 548 speedtest1_end_test(); | |
| 549 | |
| 550 | |
| 551 n = 10; | |
| 552 speedtest1_begin_test(142, "%d SELECTS w/ORDER BY, unindexed", n); | |
| 553 speedtest1_exec("BEGIN"); | |
| 554 speedtest1_prepare( | |
| 555 "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" | |
| 556 " ORDER BY a; -- %d times", n | |
| 557 ); | |
| 558 for(i=1; i<=n; i++){ | |
| 559 x1 = speedtest1_random()%maxb; | |
| 560 zNum[0] = '%'; | |
| 561 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); | |
| 562 zNum[len] = '%'; | |
| 563 zNum[len+1] = 0; | |
| 564 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); | |
| 565 speedtest1_run(); | |
| 566 } | |
| 567 speedtest1_exec("COMMIT"); | |
| 568 speedtest1_end_test(); | |
| 569 | |
| 570 n = 10; /* g.szTest/5; */ | |
| 571 speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n); | |
| 572 speedtest1_exec("BEGIN"); | |
| 573 speedtest1_prepare( | |
| 574 "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" | |
| 575 " ORDER BY a LIMIT 10; -- %d times", n | |
| 576 ); | |
| 577 for(i=1; i<=n; i++){ | |
| 578 x1 = speedtest1_random()%maxb; | |
| 579 zNum[0] = '%'; | |
| 580 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); | |
| 581 zNum[len] = '%'; | |
| 582 zNum[len+1] = 0; | |
| 583 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); | |
| 584 speedtest1_run(); | |
| 585 } | |
| 586 speedtest1_exec("COMMIT"); | |
| 587 speedtest1_end_test(); | |
| 588 | |
| 589 | |
| 590 speedtest1_begin_test(150, "CREATE INDEX five times"); | |
| 591 speedtest1_exec("BEGIN;"); | |
| 592 speedtest1_exec("CREATE UNIQUE INDEX t1b ON t1(b);"); | |
| 593 speedtest1_exec("CREATE INDEX t1c ON t1(c);"); | |
| 594 speedtest1_exec("CREATE UNIQUE INDEX t2b ON t2(b);"); | |
| 595 speedtest1_exec("CREATE INDEX t2c ON t2(c DESC);"); | |
| 596 speedtest1_exec("CREATE INDEX t3bc ON t3(b,c);"); | |
| 597 speedtest1_exec("COMMIT;"); | |
| 598 speedtest1_end_test(); | |
| 599 | |
| 600 | |
| 601 n = sz/5; | |
| 602 speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n); | |
| 603 speedtest1_exec("BEGIN"); | |
| 604 speedtest1_prepare( | |
| 605 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" | |
| 606 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n | |
| 607 ); | |
| 608 for(i=1; i<=n; i++){ | |
| 609 x1 = speedtest1_random()%maxb; | |
| 610 x2 = speedtest1_random()%10 + sz/5000 + x1; | |
| 611 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 612 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 613 speedtest1_run(); | |
| 614 } | |
| 615 speedtest1_exec("COMMIT"); | |
| 616 speedtest1_end_test(); | |
| 617 | |
| 618 | |
| 619 n = sz/5; | |
| 620 speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n); | |
| 621 speedtest1_exec("BEGIN"); | |
| 622 speedtest1_prepare( | |
| 623 "SELECT count(*), avg(b), sum(length(c)) FROM t2\n" | |
| 624 " WHERE a BETWEEN ?1 AND ?2; -- %d times", n | |
| 625 ); | |
| 626 for(i=1; i<=n; i++){ | |
| 627 x1 = speedtest1_random()%maxb; | |
| 628 x2 = speedtest1_random()%10 + sz/5000 + x1; | |
| 629 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 630 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 631 speedtest1_run(); | |
| 632 } | |
| 633 speedtest1_exec("COMMIT"); | |
| 634 speedtest1_end_test(); | |
| 635 | |
| 636 | |
| 637 n = sz/5; | |
| 638 speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n); | |
| 639 speedtest1_exec("BEGIN"); | |
| 640 speedtest1_prepare( | |
| 641 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" | |
| 642 " WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n | |
| 643 ); | |
| 644 for(i=1; i<=n; i++){ | |
| 645 x1 = swizzle(i, maxb); | |
| 646 len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1); | |
| 647 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); | |
| 648 speedtest1_run(); | |
| 649 } | |
| 650 speedtest1_exec("COMMIT"); | |
| 651 speedtest1_end_test(); | |
| 652 | |
| 653 n = sz; | |
| 654 speedtest1_begin_test(180, "%d INSERTS with three indexes", n); | |
| 655 speedtest1_exec("BEGIN"); | |
| 656 speedtest1_exec( | |
| 657 "CREATE TABLE t4(\n" | |
| 658 " a INTEGER %s %s,\n" | |
| 659 " b INTEGER %s,\n" | |
| 660 " c TEXT %s\n" | |
| 661 ") %s", | |
| 662 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); | |
| 663 speedtest1_exec("CREATE INDEX t4b ON t4(b)"); | |
| 664 speedtest1_exec("CREATE INDEX t4c ON t4(c)"); | |
| 665 speedtest1_exec("INSERT INTO t4 SELECT * FROM t1"); | |
| 666 speedtest1_exec("COMMIT"); | |
| 667 speedtest1_end_test(); | |
| 668 | |
| 669 n = sz; | |
| 670 speedtest1_begin_test(190, "DELETE and REFILL one table", n); | |
| 671 speedtest1_exec("DELETE FROM t2;"); | |
| 672 speedtest1_exec("INSERT INTO t2 SELECT * FROM t1;"); | |
| 673 speedtest1_end_test(); | |
| 674 | |
| 675 | |
| 676 speedtest1_begin_test(200, "VACUUM"); | |
| 677 speedtest1_exec("VACUUM"); | |
| 678 speedtest1_end_test(); | |
| 679 | |
| 680 | |
| 681 speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query"); | |
| 682 speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123"); | |
| 683 speedtest1_exec("SELECT sum(d) FROM t2"); | |
| 684 speedtest1_end_test(); | |
| 685 | |
| 686 | |
| 687 n = sz/5; | |
| 688 speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n); | |
| 689 speedtest1_exec("BEGIN"); | |
| 690 speedtest1_prepare( | |
| 691 "UPDATE t2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n | |
| 692 ); | |
| 693 for(i=1; i<=n; i++){ | |
| 694 x1 = speedtest1_random()%maxb; | |
| 695 x2 = speedtest1_random()%10 + sz/5000 + x1; | |
| 696 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 697 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 698 speedtest1_run(); | |
| 699 } | |
| 700 speedtest1_exec("COMMIT"); | |
| 701 speedtest1_end_test(); | |
| 702 | |
| 703 | |
| 704 n = sz; | |
| 705 speedtest1_begin_test(240, "%d UPDATES of individual rows", n); | |
| 706 speedtest1_exec("BEGIN"); | |
| 707 speedtest1_prepare( | |
| 708 "UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n | |
| 709 ); | |
| 710 for(i=1; i<=n; i++){ | |
| 711 x1 = speedtest1_random()%sz + 1; | |
| 712 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 713 speedtest1_run(); | |
| 714 } | |
| 715 speedtest1_exec("COMMIT"); | |
| 716 speedtest1_end_test(); | |
| 717 | |
| 718 speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz); | |
| 719 speedtest1_exec("UPDATE t2 SET d=b*4"); | |
| 720 speedtest1_end_test(); | |
| 721 | |
| 722 | |
| 723 speedtest1_begin_test(260, "Query added column after filling"); | |
| 724 speedtest1_exec("SELECT sum(d) FROM t2"); | |
| 725 speedtest1_end_test(); | |
| 726 | |
| 727 | |
| 728 | |
| 729 n = sz/5; | |
| 730 speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n); | |
| 731 speedtest1_exec("BEGIN"); | |
| 732 speedtest1_prepare( | |
| 733 "DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n | |
| 734 ); | |
| 735 for(i=1; i<=n; i++){ | |
| 736 x1 = speedtest1_random()%maxb + 1; | |
| 737 x2 = speedtest1_random()%10 + sz/5000 + x1; | |
| 738 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 739 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 740 speedtest1_run(); | |
| 741 } | |
| 742 speedtest1_exec("COMMIT"); | |
| 743 speedtest1_end_test(); | |
| 744 | |
| 745 | |
| 746 n = sz; | |
| 747 speedtest1_begin_test(280, "%d DELETEs of individual rows", n); | |
| 748 speedtest1_exec("BEGIN"); | |
| 749 speedtest1_prepare( | |
| 750 "DELETE FROM t3 WHERE a=?1; -- %d times", n | |
| 751 ); | |
| 752 for(i=1; i<=n; i++){ | |
| 753 x1 = speedtest1_random()%sz + 1; | |
| 754 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 755 speedtest1_run(); | |
| 756 } | |
| 757 speedtest1_exec("COMMIT"); | |
| 758 speedtest1_end_test(); | |
| 759 | |
| 760 | |
| 761 speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz); | |
| 762 speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1"); | |
| 763 speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1"); | |
| 764 speedtest1_end_test(); | |
| 765 | |
| 766 speedtest1_begin_test(300, "Refill a %d-row table using (b&1)==(a&1)", sz); | |
| 767 speedtest1_exec("DELETE FROM t2;"); | |
| 768 speedtest1_exec("INSERT INTO t2(a,b,c)\n" | |
| 769 " SELECT a,b,c FROM t1 WHERE (b&1)==(a&1);"); | |
| 770 speedtest1_exec("INSERT INTO t2(a,b,c)\n" | |
| 771 " SELECT a,b,c FROM t1 WHERE (b&1)<>(a&1);"); | |
| 772 speedtest1_end_test(); | |
| 773 | |
| 774 | |
| 775 n = sz/5; | |
| 776 speedtest1_begin_test(310, "%d four-ways joins", n); | |
| 777 speedtest1_exec("BEGIN"); | |
| 778 speedtest1_prepare( | |
| 779 "SELECT t1.c FROM t1, t2, t3, t4\n" | |
| 780 " WHERE t4.a BETWEEN ?1 AND ?2\n" | |
| 781 " AND t3.a=t4.b\n" | |
| 782 " AND t2.a=t3.b\n" | |
| 783 " AND t1.c=t2.c" | |
| 784 ); | |
| 785 for(i=1; i<=n; i++){ | |
| 786 x1 = speedtest1_random()%sz + 1; | |
| 787 x2 = speedtest1_random()%10 + x1 + 4; | |
| 788 sqlite3_bind_int(g.pStmt, 1, x1); | |
| 789 sqlite3_bind_int(g.pStmt, 2, x2); | |
| 790 speedtest1_run(); | |
| 791 } | |
| 792 speedtest1_exec("COMMIT"); | |
| 793 speedtest1_end_test(); | |
| 794 | |
| 795 speedtest1_begin_test(320, "subquery in result set", n); | |
| 796 speedtest1_prepare( | |
| 797 "SELECT sum(a), max(c),\n" | |
| 798 " avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n" | |
| 799 " FROM t1 WHERE rowid<?1;" | |
| 800 ); | |
| 801 sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50); | |
| 802 speedtest1_run(); | |
| 803 speedtest1_end_test(); | |
| 804 | |
| 805 speedtest1_begin_test(980, "PRAGMA integrity_check"); | |
| 806 speedtest1_exec("PRAGMA integrity_check"); | |
| 807 speedtest1_end_test(); | |
| 808 | |
| 809 | |
| 810 speedtest1_begin_test(990, "ANALYZE"); | |
| 811 speedtest1_exec("ANALYZE"); | |
| 812 speedtest1_end_test(); | |
| 813 } | |
| 814 | |
| 815 /* | |
| 816 ** A testset for common table expressions. This exercises code | |
| 817 ** for views, subqueries, co-routines, etc. | |
| 818 */ | |
| 819 void testset_cte(void){ | |
| 820 static const char *azPuzzle[] = { | |
| 821 /* Easy */ | |
| 822 "534...9.." | |
| 823 "67.195..." | |
| 824 ".98....6." | |
| 825 "8...6...3" | |
| 826 "4..8.3..1" | |
| 827 "....2...6" | |
| 828 ".6....28." | |
| 829 "...419..5" | |
| 830 "...28..79", | |
| 831 | |
| 832 /* Medium */ | |
| 833 "53....9.." | |
| 834 "6..195..." | |
| 835 ".98....6." | |
| 836 "8...6...3" | |
| 837 "4..8.3..1" | |
| 838 "....2...6" | |
| 839 ".6....28." | |
| 840 "...419..5" | |
| 841 "....8..79", | |
| 842 | |
| 843 /* Hard */ | |
| 844 "53......." | |
| 845 "6..195..." | |
| 846 ".98....6." | |
| 847 "8...6...3" | |
| 848 "4..8.3..1" | |
| 849 "....2...6" | |
| 850 ".6....28." | |
| 851 "...419..5" | |
| 852 "....8..79", | |
| 853 }; | |
| 854 const char *zPuz; | |
| 855 double rSpacing; | |
| 856 int nElem; | |
| 857 | |
| 858 if( g.szTest<25 ){ | |
| 859 zPuz = azPuzzle[0]; | |
| 860 }else if( g.szTest<70 ){ | |
| 861 zPuz = azPuzzle[1]; | |
| 862 }else{ | |
| 863 zPuz = azPuzzle[2]; | |
| 864 } | |
| 865 speedtest1_begin_test(100, "Sudoku with recursive 'digits'"); | |
| 866 speedtest1_prepare( | |
| 867 "WITH RECURSIVE\n" | |
| 868 " input(sud) AS (VALUES(?1)),\n" | |
| 869 " digits(z,lp) AS (\n" | |
| 870 " VALUES('1', 1)\n" | |
| 871 " UNION ALL\n" | |
| 872 " SELECT CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<9\n" | |
| 873 " ),\n" | |
| 874 " x(s, ind) AS (\n" | |
| 875 " SELECT sud, instr(sud, '.') FROM input\n" | |
| 876 " UNION ALL\n" | |
| 877 " SELECT\n" | |
| 878 " substr(s, 1, ind-1) || z || substr(s, ind+1),\n" | |
| 879 " instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n" | |
| 880 " FROM x, digits AS z\n" | |
| 881 " WHERE ind>0\n" | |
| 882 " AND NOT EXISTS (\n" | |
| 883 " SELECT 1\n" | |
| 884 " FROM digits AS lp\n" | |
| 885 " WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n" | |
| 886 " OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n" | |
| 887 " OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n" | |
| 888 " + ((ind-1)/27) * 27 + lp\n" | |
| 889 " + ((lp-1) / 3) * 6, 1)\n" | |
| 890 " )\n" | |
| 891 " )\n" | |
| 892 "SELECT s FROM x WHERE ind=0;" | |
| 893 ); | |
| 894 sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC); | |
| 895 speedtest1_run(); | |
| 896 speedtest1_end_test(); | |
| 897 | |
| 898 speedtest1_begin_test(200, "Sudoku with VALUES 'digits'"); | |
| 899 speedtest1_prepare( | |
| 900 "WITH RECURSIVE\n" | |
| 901 " input(sud) AS (VALUES(?1)),\n" | |
| 902 " digits(z,lp) AS (VALUES('1',1),('2',2),('3',3),('4',4),('5',5),\n" | |
| 903 " ('6',6),('7',7),('8',8),('9',9)),\n" | |
| 904 " x(s, ind) AS (\n" | |
| 905 " SELECT sud, instr(sud, '.') FROM input\n" | |
| 906 " UNION ALL\n" | |
| 907 " SELECT\n" | |
| 908 " substr(s, 1, ind-1) || z || substr(s, ind+1),\n" | |
| 909 " instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n" | |
| 910 " FROM x, digits AS z\n" | |
| 911 " WHERE ind>0\n" | |
| 912 " AND NOT EXISTS (\n" | |
| 913 " SELECT 1\n" | |
| 914 " FROM digits AS lp\n" | |
| 915 " WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n" | |
| 916 " OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n" | |
| 917 " OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n" | |
| 918 " + ((ind-1)/27) * 27 + lp\n" | |
| 919 " + ((lp-1) / 3) * 6, 1)\n" | |
| 920 " )\n" | |
| 921 " )\n" | |
| 922 "SELECT s FROM x WHERE ind=0;" | |
| 923 ); | |
| 924 sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC); | |
| 925 speedtest1_run(); | |
| 926 speedtest1_end_test(); | |
| 927 | |
| 928 rSpacing = 5.0/g.szTest; | |
| 929 speedtest1_begin_test(300, "Mandelbrot Set with spacing=%f", rSpacing); | |
| 930 speedtest1_prepare( | |
| 931 "WITH RECURSIVE \n" | |
| 932 " xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+?1 FROM xaxis WHERE x<1.2),\n
" | |
| 933 " yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+?2 FROM yaxis WHERE y<1.0),\n
" | |
| 934 " m(iter, cx, cy, x, y) AS (\n" | |
| 935 " SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis\n" | |
| 936 " UNION ALL\n" | |
| 937 " SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m \n" | |
| 938 " WHERE (x*x + y*y) < 4.0 AND iter<28\n" | |
| 939 " ),\n" | |
| 940 " m2(iter, cx, cy) AS (\n" | |
| 941 " SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n" | |
| 942 " ),\n" | |
| 943 " a(t) AS (\n" | |
| 944 " SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n" | |
| 945 " FROM m2 GROUP BY cy\n" | |
| 946 " )\n" | |
| 947 "SELECT group_concat(rtrim(t),x'0a') FROM a;" | |
| 948 ); | |
| 949 sqlite3_bind_double(g.pStmt, 1, rSpacing*.05); | |
| 950 sqlite3_bind_double(g.pStmt, 2, rSpacing); | |
| 951 speedtest1_run(); | |
| 952 speedtest1_end_test(); | |
| 953 | |
| 954 nElem = 10000*g.szTest; | |
| 955 speedtest1_begin_test(400, "EXCEPT operator on %d-element tables", nElem); | |
| 956 speedtest1_prepare( | |
| 957 "WITH RECURSIVE \n" | |
| 958 " t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<%d),\n" | |
| 959 " t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<%d)\n" | |
| 960 "SELECT count(x), avg(x) FROM (\n" | |
| 961 " SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1\n" | |
| 962 ");", | |
| 963 nElem, nElem | |
| 964 ); | |
| 965 speedtest1_run(); | |
| 966 speedtest1_end_test(); | |
| 967 | |
| 968 } | |
| 969 | |
| 970 #ifdef SQLITE_ENABLE_RTREE | |
| 971 /* Generate two numbers between 1 and mx. The first number is less than | |
| 972 ** the second. Usually the numbers are near each other but can sometimes | |
| 973 ** be far apart. | |
| 974 */ | |
| 975 static void twoCoords( | |
| 976 int p1, int p2, /* Parameters adjusting sizes */ | |
| 977 unsigned mx, /* Range of 1..mx */ | |
| 978 unsigned *pX0, unsigned *pX1 /* OUT: write results here */ | |
| 979 ){ | |
| 980 unsigned d, x0, x1, span; | |
| 981 | |
| 982 span = mx/100 + 1; | |
| 983 if( speedtest1_random()%3==0 ) span *= p1; | |
| 984 if( speedtest1_random()%p2==0 ) span = mx/2; | |
| 985 d = speedtest1_random()%span + 1; | |
| 986 x0 = speedtest1_random()%(mx-d) + 1; | |
| 987 x1 = x0 + d; | |
| 988 *pX0 = x0; | |
| 989 *pX1 = x1; | |
| 990 } | |
| 991 #endif | |
| 992 | |
| 993 #ifdef SQLITE_ENABLE_RTREE | |
| 994 /* The following routine is an R-Tree geometry callback. It returns | |
| 995 ** true if the object overlaps a slice on the Y coordinate between the | |
| 996 ** two values given as arguments. In other words | |
| 997 ** | |
| 998 ** SELECT count(*) FROM rt1 WHERE id MATCH xslice(10,20); | |
| 999 ** | |
| 1000 ** Is the same as saying: | |
| 1001 ** | |
| 1002 ** SELECT count(*) FROM rt1 WHERE y1>=10 AND y0<=20; | |
| 1003 */ | |
| 1004 static int xsliceGeometryCallback( | |
| 1005 sqlite3_rtree_geometry *p, | |
| 1006 int nCoord, | |
| 1007 double *aCoord, | |
| 1008 int *pRes | |
| 1009 ){ | |
| 1010 *pRes = aCoord[3]>=p->aParam[0] && aCoord[2]<=p->aParam[1]; | |
| 1011 return SQLITE_OK; | |
| 1012 } | |
| 1013 #endif /* SQLITE_ENABLE_RTREE */ | |
| 1014 | |
| 1015 #ifdef SQLITE_ENABLE_RTREE | |
| 1016 /* | |
| 1017 ** A testset for the R-Tree virtual table | |
| 1018 */ | |
| 1019 void testset_rtree(int p1, int p2){ | |
| 1020 unsigned i, n; | |
| 1021 unsigned mxCoord; | |
| 1022 unsigned x0, x1, y0, y1, z0, z1; | |
| 1023 unsigned iStep; | |
| 1024 int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 ); | |
| 1025 | |
| 1026 mxCoord = 15000; | |
| 1027 n = g.szTest*100; | |
| 1028 speedtest1_begin_test(100, "%d INSERTs into an r-tree", n); | |
| 1029 speedtest1_exec("BEGIN"); | |
| 1030 speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)"); | |
| 1031 speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)" | |
| 1032 "VALUES(?1,?2,?3,?4,?5,?6,?7)"); | |
| 1033 for(i=1; i<=n; i++){ | |
| 1034 twoCoords(p1, p2, mxCoord, &x0, &x1); | |
| 1035 twoCoords(p1, p2, mxCoord, &y0, &y1); | |
| 1036 twoCoords(p1, p2, mxCoord, &z0, &z1); | |
| 1037 sqlite3_bind_int(g.pStmt, 1, i); | |
| 1038 sqlite3_bind_int(g.pStmt, 2, x0); | |
| 1039 sqlite3_bind_int(g.pStmt, 3, x1); | |
| 1040 sqlite3_bind_int(g.pStmt, 4, y0); | |
| 1041 sqlite3_bind_int(g.pStmt, 5, y1); | |
| 1042 sqlite3_bind_int(g.pStmt, 6, z0); | |
| 1043 sqlite3_bind_int(g.pStmt, 7, z1); | |
| 1044 speedtest1_run(); | |
| 1045 } | |
| 1046 speedtest1_exec("COMMIT"); | |
| 1047 speedtest1_end_test(); | |
| 1048 | |
| 1049 speedtest1_begin_test(101, "Copy from rtree to a regular table"); | |
| 1050 speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)"); | |
| 1051 speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1"); | |
| 1052 speedtest1_end_test(); | |
| 1053 | |
| 1054 n = g.szTest*20; | |
| 1055 speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n); | |
| 1056 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2"); | |
| 1057 iStep = mxCoord/n; | |
| 1058 for(i=0; i<n; i++){ | |
| 1059 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1060 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1061 speedtest1_run(); | |
| 1062 aCheck[i] = atoi(g.zResult); | |
| 1063 } | |
| 1064 speedtest1_end_test(); | |
| 1065 | |
| 1066 if( g.bVerify ){ | |
| 1067 n = g.szTest*20; | |
| 1068 speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries")
; | |
| 1069 speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2"); | |
| 1070 iStep = mxCoord/n; | |
| 1071 for(i=0; i<n; i++){ | |
| 1072 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1073 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1074 speedtest1_run(); | |
| 1075 if( aCheck[i]!=atoi(g.zResult) ){ | |
| 1076 fatal_error("Count disagree step %d: %d..%d. %d vs %d", | |
| 1077 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); | |
| 1078 } | |
| 1079 } | |
| 1080 speedtest1_end_test(); | |
| 1081 } | |
| 1082 | |
| 1083 n = g.szTest*20; | |
| 1084 speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n); | |
| 1085 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2"); | |
| 1086 iStep = mxCoord/n; | |
| 1087 for(i=0; i<n; i++){ | |
| 1088 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1089 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1090 speedtest1_run(); | |
| 1091 aCheck[i] = atoi(g.zResult); | |
| 1092 } | |
| 1093 speedtest1_end_test(); | |
| 1094 | |
| 1095 if( g.bVerify ){ | |
| 1096 n = g.szTest*20; | |
| 1097 speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries"); | |
| 1098 speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2"); | |
| 1099 iStep = mxCoord/n; | |
| 1100 for(i=0; i<n; i++){ | |
| 1101 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1102 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1103 speedtest1_run(); | |
| 1104 if( aCheck[i]!=atoi(g.zResult) ){ | |
| 1105 fatal_error("Count disagree step %d: %d..%d. %d vs %d", | |
| 1106 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); | |
| 1107 } | |
| 1108 } | |
| 1109 speedtest1_end_test(); | |
| 1110 } | |
| 1111 | |
| 1112 | |
| 1113 n = g.szTest*20; | |
| 1114 speedtest1_begin_test(125, "%d custom geometry callback queries", n); | |
| 1115 sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0); | |
| 1116 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)"); | |
| 1117 iStep = mxCoord/n; | |
| 1118 for(i=0; i<n; i++){ | |
| 1119 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1120 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1121 speedtest1_run(); | |
| 1122 if( aCheck[i]!=atoi(g.zResult) ){ | |
| 1123 fatal_error("Count disagree step %d: %d..%d. %d vs %d", | |
| 1124 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); | |
| 1125 } | |
| 1126 } | |
| 1127 speedtest1_end_test(); | |
| 1128 | |
| 1129 n = g.szTest*80; | |
| 1130 speedtest1_begin_test(130, "%d three-dimensional intersect box queries", n); | |
| 1131 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x1>=?1 AND x0<=?2" | |
| 1132 " AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2"); | |
| 1133 iStep = mxCoord/n; | |
| 1134 for(i=0; i<n; i++){ | |
| 1135 sqlite3_bind_int(g.pStmt, 1, i*iStep); | |
| 1136 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); | |
| 1137 speedtest1_run(); | |
| 1138 aCheck[i] = atoi(g.zResult); | |
| 1139 } | |
| 1140 speedtest1_end_test(); | |
| 1141 | |
| 1142 n = g.szTest*100; | |
| 1143 speedtest1_begin_test(140, "%d rowid queries", n); | |
| 1144 speedtest1_prepare("SELECT * FROM rt1 WHERE id=?1"); | |
| 1145 for(i=1; i<=n; i++){ | |
| 1146 sqlite3_bind_int(g.pStmt, 1, i); | |
| 1147 speedtest1_run(); | |
| 1148 } | |
| 1149 speedtest1_end_test(); | |
| 1150 } | |
| 1151 #endif /* SQLITE_ENABLE_RTREE */ | |
| 1152 | |
| 1153 /* | |
| 1154 ** A testset used for debugging speedtest1 itself. | |
| 1155 */ | |
| 1156 void testset_debug1(void){ | |
| 1157 unsigned i, n; | |
| 1158 unsigned x1, x2; | |
| 1159 char zNum[2000]; /* A number name */ | |
| 1160 | |
| 1161 n = g.szTest; | |
| 1162 for(i=1; i<=n; i++){ | |
| 1163 x1 = swizzle(i, n); | |
| 1164 x2 = swizzle(x1, n); | |
| 1165 speedtest1_numbername(x1, zNum, sizeof(zNum)); | |
| 1166 printf("%5d %5d %5d %s\n", i, x1, x2, zNum); | |
| 1167 } | |
| 1168 } | |
| 1169 | |
| 1170 int main(int argc, char **argv){ | |
| 1171 int doAutovac = 0; /* True for --autovacuum */ | |
| 1172 int cacheSize = 0; /* Desired cache size. 0 means default */ | |
| 1173 int doExclusive = 0; /* True for --exclusive */ | |
| 1174 int nHeap = 0, mnHeap = 0; /* Heap size from --heap */ | |
| 1175 int doIncrvac = 0; /* True for --incrvacuum */ | |
| 1176 const char *zJMode = 0; /* Journal mode */ | |
| 1177 const char *zKey = 0; /* Encryption key */ | |
| 1178 int nLook = 0, szLook = 0; /* --lookaside configuration */ | |
| 1179 int noSync = 0; /* True for --nosync */ | |
| 1180 int pageSize = 0; /* Desired page size. 0 means default */ | |
| 1181 int nPCache = 0, szPCache = 0;/* --pcache configuration */ | |
| 1182 int doPCache = 0; /* True if --pcache is seen */ | |
| 1183 int nScratch = 0, szScratch=0;/* --scratch configuration */ | |
| 1184 int showStats = 0; /* True for --stats */ | |
| 1185 int nThread = 0; /* --threads value */ | |
| 1186 const char *zTSet = "main"; /* Which --testset torun */ | |
| 1187 int doTrace = 0; /* True for --trace */ | |
| 1188 const char *zEncoding = 0; /* --utf16be or --utf16le */ | |
| 1189 const char *zDbName = 0; /* Name of the test database */ | |
| 1190 | |
| 1191 void *pHeap = 0; /* Allocated heap space */ | |
| 1192 void *pLook = 0; /* Allocated lookaside space */ | |
| 1193 void *pPCache = 0; /* Allocated storage for pcache */ | |
| 1194 void *pScratch = 0; /* Allocated storage for scratch */ | |
| 1195 int iCur, iHi; /* Stats values, current and "highwater" */ | |
| 1196 int i; /* Loop counter */ | |
| 1197 int rc; /* API return code */ | |
| 1198 | |
| 1199 /* Process command-line arguments */ | |
| 1200 g.zWR = ""; | |
| 1201 g.zNN = ""; | |
| 1202 g.zPK = "UNIQUE"; | |
| 1203 g.szTest = 100; | |
| 1204 for(i=1; i<argc; i++){ | |
| 1205 const char *z = argv[i]; | |
| 1206 if( z[0]=='-' ){ | |
| 1207 do{ z++; }while( z[0]=='-' ); | |
| 1208 if( strcmp(z,"autovacuum")==0 ){ | |
| 1209 doAutovac = 1; | |
| 1210 }else if( strcmp(z,"cachesize")==0 ){ | |
| 1211 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1212 i++; | |
| 1213 cacheSize = integerValue(argv[i]); | |
| 1214 }else if( strcmp(z,"exclusive")==0 ){ | |
| 1215 doExclusive = 1; | |
| 1216 }else if( strcmp(z,"explain")==0 ){ | |
| 1217 g.bSqlOnly = 1; | |
| 1218 g.bExplain = 1; | |
| 1219 }else if( strcmp(z,"heap")==0 ){ | |
| 1220 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); | |
| 1221 nHeap = integerValue(argv[i+1]); | |
| 1222 mnHeap = integerValue(argv[i+2]); | |
| 1223 i += 2; | |
| 1224 }else if( strcmp(z,"incrvacuum")==0 ){ | |
| 1225 doIncrvac = 1; | |
| 1226 }else if( strcmp(z,"journal")==0 ){ | |
| 1227 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1228 zJMode = argv[++i]; | |
| 1229 }else if( strcmp(z,"key")==0 ){ | |
| 1230 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1231 zKey = argv[++i]; | |
| 1232 }else if( strcmp(z,"lookaside")==0 ){ | |
| 1233 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); | |
| 1234 nLook = integerValue(argv[i+1]); | |
| 1235 szLook = integerValue(argv[i+2]); | |
| 1236 i += 2; | |
| 1237 }else if( strcmp(z,"multithread")==0 ){ | |
| 1238 sqlite3_config(SQLITE_CONFIG_MULTITHREAD); | |
| 1239 }else if( strcmp(z,"nomemstat")==0 ){ | |
| 1240 sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0); | |
| 1241 }else if( strcmp(z,"nosync")==0 ){ | |
| 1242 noSync = 1; | |
| 1243 }else if( strcmp(z,"notnull")==0 ){ | |
| 1244 g.zNN = "NOT NULL"; | |
| 1245 #ifdef SQLITE_ENABLE_RBU | |
| 1246 }else if( strcmp(z,"rbu")==0 ){ | |
| 1247 sqlite3ota_create_vfs("rbu", 0); | |
| 1248 sqlite3_vfs_register(sqlite3_vfs_find("rbu"), 1); | |
| 1249 #endif | |
| 1250 }else if( strcmp(z,"pagesize")==0 ){ | |
| 1251 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1252 pageSize = integerValue(argv[++i]); | |
| 1253 }else if( strcmp(z,"pcache")==0 ){ | |
| 1254 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); | |
| 1255 nPCache = integerValue(argv[i+1]); | |
| 1256 szPCache = integerValue(argv[i+2]); | |
| 1257 doPCache = 1; | |
| 1258 i += 2; | |
| 1259 }else if( strcmp(z,"primarykey")==0 ){ | |
| 1260 g.zPK = "PRIMARY KEY"; | |
| 1261 }else if( strcmp(z,"reprepare")==0 ){ | |
| 1262 g.bReprepare = 1; | |
| 1263 }else if( strcmp(z,"scratch")==0 ){ | |
| 1264 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); | |
| 1265 nScratch = integerValue(argv[i+1]); | |
| 1266 szScratch = integerValue(argv[i+2]); | |
| 1267 i += 2; | |
| 1268 }else if( strcmp(z,"serialized")==0 ){ | |
| 1269 sqlite3_config(SQLITE_CONFIG_SERIALIZED); | |
| 1270 }else if( strcmp(z,"singlethread")==0 ){ | |
| 1271 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); | |
| 1272 }else if( strcmp(z,"sqlonly")==0 ){ | |
| 1273 g.bSqlOnly = 1; | |
| 1274 }else if( strcmp(z,"shrink-memory")==0 ){ | |
| 1275 g.bMemShrink = 1; | |
| 1276 }else if( strcmp(z,"size")==0 ){ | |
| 1277 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1278 g.szTest = integerValue(argv[++i]); | |
| 1279 }else if( strcmp(z,"stats")==0 ){ | |
| 1280 showStats = 1; | |
| 1281 }else if( strcmp(z,"testset")==0 ){ | |
| 1282 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1283 zTSet = argv[++i]; | |
| 1284 }else if( strcmp(z,"trace")==0 ){ | |
| 1285 doTrace = 1; | |
| 1286 }else if( strcmp(z,"threads")==0 ){ | |
| 1287 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); | |
| 1288 nThread = integerValue(argv[++i]); | |
| 1289 }else if( strcmp(z,"utf16le")==0 ){ | |
| 1290 zEncoding = "utf16le"; | |
| 1291 }else if( strcmp(z,"utf16be")==0 ){ | |
| 1292 zEncoding = "utf16be"; | |
| 1293 }else if( strcmp(z,"verify")==0 ){ | |
| 1294 g.bVerify = 1; | |
| 1295 }else if( strcmp(z,"without-rowid")==0 ){ | |
| 1296 g.zWR = "WITHOUT ROWID"; | |
| 1297 g.zPK = "PRIMARY KEY"; | |
| 1298 }else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){ | |
| 1299 printf(zHelp, argv[0]); | |
| 1300 exit(0); | |
| 1301 }else{ | |
| 1302 fatal_error("unknown option: %s\nUse \"%s -?\" for help\n", | |
| 1303 argv[i], argv[0]); | |
| 1304 } | |
| 1305 }else if( zDbName==0 ){ | |
| 1306 zDbName = argv[i]; | |
| 1307 }else{ | |
| 1308 fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n", | |
| 1309 argv[i], argv[0]); | |
| 1310 } | |
| 1311 } | |
| 1312 #if 0 | |
| 1313 if( zDbName==0 ){ | |
| 1314 fatal_error(zHelp, argv[0]); | |
| 1315 } | |
| 1316 #endif | |
| 1317 #if SQLITE_VERSION_NUMBER>=3006001 | |
| 1318 if( nHeap>0 ){ | |
| 1319 pHeap = malloc( nHeap ); | |
| 1320 if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap); | |
| 1321 rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap); | |
| 1322 if( rc ) fatal_error("heap configuration failed: %d\n", rc); | |
| 1323 } | |
| 1324 if( doPCache ){ | |
| 1325 if( nPCache>0 && szPCache>0 ){ | |
| 1326 pPCache = malloc( nPCache*(sqlite3_int64)szPCache ); | |
| 1327 if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n", | |
| 1328 nPCache*(sqlite3_int64)szPCache); | |
| 1329 } | |
| 1330 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache); | |
| 1331 if( rc ) fatal_error("pcache configuration failed: %d\n", rc); | |
| 1332 } | |
| 1333 if( nScratch>0 && szScratch>0 ){ | |
| 1334 pScratch = malloc( nScratch*(sqlite3_int64)szScratch ); | |
| 1335 if( pScratch==0 ) fatal_error("cannot allocate %lld-byte scratch\n", | |
| 1336 nScratch*(sqlite3_int64)szScratch); | |
| 1337 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch); | |
| 1338 if( rc ) fatal_error("scratch configuration failed: %d\n", rc); | |
| 1339 } | |
| 1340 if( nLook>0 ){ | |
| 1341 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); | |
| 1342 } | |
| 1343 #endif | |
| 1344 | |
| 1345 /* Open the database and the input file */ | |
| 1346 if( sqlite3_open(zDbName, &g.db) ){ | |
| 1347 fatal_error("Cannot open database file: %s\n", zDbName); | |
| 1348 } | |
| 1349 #if SQLITE_VERSION_NUMBER>=3006001 | |
| 1350 if( nLook>0 && szLook>0 ){ | |
| 1351 pLook = malloc( nLook*szLook ); | |
| 1352 rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook)
; | |
| 1353 if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); | |
| 1354 } | |
| 1355 #endif | |
| 1356 | |
| 1357 /* Set database connection options */ | |
| 1358 sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0); | |
| 1359 if( doTrace ) sqlite3_trace(g.db, traceCallback, 0); | |
| 1360 speedtest1_exec("PRAGMA threads=%d", nThread); | |
| 1361 if( zKey ){ | |
| 1362 speedtest1_exec("PRAGMA key('%s')", zKey); | |
| 1363 } | |
| 1364 if( zEncoding ){ | |
| 1365 speedtest1_exec("PRAGMA encoding=%s", zEncoding); | |
| 1366 } | |
| 1367 if( doAutovac ){ | |
| 1368 speedtest1_exec("PRAGMA auto_vacuum=FULL"); | |
| 1369 }else if( doIncrvac ){ | |
| 1370 speedtest1_exec("PRAGMA auto_vacuum=INCREMENTAL"); | |
| 1371 } | |
| 1372 if( pageSize ){ | |
| 1373 speedtest1_exec("PRAGMA page_size=%d", pageSize); | |
| 1374 } | |
| 1375 if( cacheSize ){ | |
| 1376 speedtest1_exec("PRAGMA cache_size=%d", cacheSize); | |
| 1377 } | |
| 1378 if( noSync ) speedtest1_exec("PRAGMA synchronous=OFF"); | |
| 1379 if( doExclusive ){ | |
| 1380 speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE"); | |
| 1381 } | |
| 1382 if( zJMode ){ | |
| 1383 speedtest1_exec("PRAGMA journal_mode=%s", zJMode); | |
| 1384 } | |
| 1385 | |
| 1386 if( g.bExplain ) printf(".explain\n.echo on\n"); | |
| 1387 if( strcmp(zTSet,"main")==0 ){ | |
| 1388 testset_main(); | |
| 1389 }else if( strcmp(zTSet,"debug1")==0 ){ | |
| 1390 testset_debug1(); | |
| 1391 }else if( strcmp(zTSet,"cte")==0 ){ | |
| 1392 testset_cte(); | |
| 1393 }else if( strcmp(zTSet,"rtree")==0 ){ | |
| 1394 #ifdef SQLITE_ENABLE_RTREE | |
| 1395 testset_rtree(6, 147); | |
| 1396 #else | |
| 1397 fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable " | |
| 1398 "the R-Tree tests\n"); | |
| 1399 #endif | |
| 1400 }else{ | |
| 1401 fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n", | |
| 1402 zTSet); | |
| 1403 } | |
| 1404 speedtest1_final(); | |
| 1405 | |
| 1406 /* Database connection statistics printed after both prepared statements | |
| 1407 ** have been finalized */ | |
| 1408 #if SQLITE_VERSION_NUMBER>=3007009 | |
| 1409 if( showStats ){ | |
| 1410 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0); | |
| 1411 printf("-- Lookaside Slots Used: %d (max %d)\n", iCur,iHi); | |
| 1412 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0); | |
| 1413 printf("-- Successful lookasides: %d\n", iHi); | |
| 1414 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0); | |
| 1415 printf("-- Lookaside size faults: %d\n", iHi); | |
| 1416 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0); | |
| 1417 printf("-- Lookaside OOM faults: %d\n", iHi); | |
| 1418 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0); | |
| 1419 printf("-- Pager Heap Usage: %d bytes\n", iCur); | |
| 1420 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1); | |
| 1421 printf("-- Page cache hits: %d\n", iCur); | |
| 1422 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1); | |
| 1423 printf("-- Page cache misses: %d\n", iCur); | |
| 1424 #if SQLITE_VERSION_NUMBER>=3007012 | |
| 1425 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1); | |
| 1426 printf("-- Page cache writes: %d\n", iCur); | |
| 1427 #endif | |
| 1428 sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0); | |
| 1429 printf("-- Schema Heap Usage: %d bytes\n", iCur); | |
| 1430 sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0); | |
| 1431 printf("-- Statement Heap Usage: %d bytes\n", iCur); | |
| 1432 } | |
| 1433 #endif | |
| 1434 | |
| 1435 sqlite3_close(g.db); | |
| 1436 | |
| 1437 #if SQLITE_VERSION_NUMBER>=3006001 | |
| 1438 /* Global memory usage statistics printed after the database connection | |
| 1439 ** has closed. Memory usage should be zero at this point. */ | |
| 1440 if( showStats ){ | |
| 1441 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0); | |
| 1442 printf("-- Memory Used (bytes): %d (max %d)\n", iCur,iHi); | |
| 1443 #if SQLITE_VERSION_NUMBER>=3007000 | |
| 1444 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0); | |
| 1445 printf("-- Outstanding Allocations: %d (max %d)\n", iCur,iHi); | |
| 1446 #endif | |
| 1447 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0); | |
| 1448 printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi); | |
| 1449 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHi, 0); | |
| 1450 printf("-- Scratch Overflow Bytes: %d (max %d)\n", iCur,iHi); | |
| 1451 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0); | |
| 1452 printf("-- Largest Allocation: %d bytes\n",iHi); | |
| 1453 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0); | |
| 1454 printf("-- Largest Pcache Allocation: %d bytes\n",iHi); | |
| 1455 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0); | |
| 1456 printf("-- Largest Scratch Allocation: %d bytes\n", iHi); | |
| 1457 } | |
| 1458 #endif | |
| 1459 | |
| 1460 /* Release memory */ | |
| 1461 free( pLook ); | |
| 1462 free( pPCache ); | |
| 1463 free( pScratch ); | |
| 1464 free( pHeap ); | |
| 1465 return 0; | |
| 1466 } | |
| OLD | NEW |