SQLite

Check-in [f7f78147c5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Simplifications to faststat1.c. Fix a bug in sqlite3MovetoProportional() for very large b-trees.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | est_count_pragma
Files: files | file ages | folders
SHA1: f7f78147c5d51dfb4c46b2d9afad0648f57d54f3
User & Date: drh 2016-10-25 19:39:31.185
Context
2016-10-26
12:58
Add an elapsed-time output for faststat1.c. (check-in: 7116795134 user: drh tags: est_count_pragma)
2016-10-25
19:39
Simplifications to faststat1.c. Fix a bug in sqlite3MovetoProportional() for very large b-trees. (check-in: f7f78147c5 user: drh tags: est_count_pragma)
19:21
Further refinements to the faststat1.c utility. (check-in: b051fd19bc user: drh tags: est_count_pragma)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
5076
5077
5078
5079
5080
5081
5082

5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101

5102
5103
5104
5105
5106
5107
5108
  u16 rx;
  MemPage *pPage;
  rc = moveToRoot(pCur);
  if( rc ) return rc;
  pPage = pCur->apPage[0];
  while( !pPage->leaf ){
    perChild = (mx+pPage->nCell)/(pPage->nCell+1);

    rx = x/perChild;
    x %= perChild;
    mx = perChild;
    if( rx>=pPage->nCell ){
      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    }else{
      chldPg = get4byte(findCell(pPage,rx));
    }
    n *= pPage->nCell+1;
    pCur->aiIdx[pCur->iPage] = rx;
    rc = moveToChild(pCur, chldPg);
    if( rc ) return rc;
    pPage = pCur->apPage[pCur->iPage];
  }
  *pnRowEst = n*pPage->nCell;
  if( pPage->nCell==0 ){
    rx = 0;
  }else{
    perChild = mx/pPage->nCell;

    rx = x/perChild;
    if( rx>=pPage->nCell ) rx = pPage->nCell-1;
  }
  pCur->aiIdx[pCur->iPage] = rx;

  return SQLITE_OK;
}







>



















>







5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
  u16 rx;
  MemPage *pPage;
  rc = moveToRoot(pCur);
  if( rc ) return rc;
  pPage = pCur->apPage[0];
  while( !pPage->leaf ){
    perChild = (mx+pPage->nCell)/(pPage->nCell+1);
    if( perChild<1 ) perChild = 1;
    rx = x/perChild;
    x %= perChild;
    mx = perChild;
    if( rx>=pPage->nCell ){
      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    }else{
      chldPg = get4byte(findCell(pPage,rx));
    }
    n *= pPage->nCell+1;
    pCur->aiIdx[pCur->iPage] = rx;
    rc = moveToChild(pCur, chldPg);
    if( rc ) return rc;
    pPage = pCur->apPage[pCur->iPage];
  }
  *pnRowEst = n*pPage->nCell;
  if( pPage->nCell==0 ){
    rx = 0;
  }else{
    perChild = mx/pPage->nCell;
    if( perChild<1 ) perChild = 1;
    rx = x/perChild;
    if( rx>=pPage->nCell ) rx = pPage->nCell-1;
  }
  pCur->aiIdx[pCur->iPage] = rx;

  return SQLITE_OK;
}
Changes to tool/faststat1.c.
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  for(j=0; j<nCol; j++) sqlite3_value_free(apValue[j]);
  sqlite3_snprintf(szRes, zRes, "%lld", n);
  k = (int)strlen(zRes);
  for(j=0; j<nCol; j++){
    sqlite3_snprintf(szRes-k, zRes+k, " %d", (nRow+aCnt[j]-1)/aCnt[j]);
    k += (int)strlen(zRes+k);
  }
  pStmt = db_prepare(
     "INSERT INTO temp.est_stat1(tbl,idx,stat)"
     "VALUES(\"%w\",\"%w\",'%s')", zTab, zIdx, zRes
  );
  sqlite3_step(pStmt);
  sqlite3_finalize(pStmt);
  return 1;
}

/*
** Stat1 for a table.
*/
static void analyzeTable(const char *zTab){







<
|
|
<
<
<







232
233
234
235
236
237
238

239
240



241
242
243
244
245
246
247
  for(j=0; j<nCol; j++) sqlite3_value_free(apValue[j]);
  sqlite3_snprintf(szRes, zRes, "%lld", n);
  k = (int)strlen(zRes);
  for(j=0; j<nCol; j++){
    sqlite3_snprintf(szRes-k, zRes+k, " %d", (nRow+aCnt[j]-1)/aCnt[j]);
    k += (int)strlen(zRes+k);
  }

  printf("INSERT INTO sqlite_stat1 VALUES('%s','%s','%s');\n",
         zTab, zIdx, zRes);



  return 1;
}

/*
** Stat1 for a table.
*/
static void analyzeTable(const char *zTab){
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    if( sqlite3_column_text(pStmt,3)[0]=='p' && isWithoutRowid ) continue;
    if( sqlite3_column_int(pStmt,4)==0 ) nIndex++;
    analyzeIndex(zTab, (const char*)sqlite3_column_text(pStmt,1));
  }
  sqlite3_finalize(pStmt);
  if( nIndex==0 ){
    pStmt = db_prepare(
       "INSERT INTO temp.est_stat1(tbl,idx,stat)"
       "VALUES(\"%w\",NULL,'%lld')", zTab, n
    );
    sqlite3_step(pStmt);
    sqlite3_finalize(pStmt);
  }
}


/*
** Print the sqlite3_value X as an SQL literal.
*/
static void printQuoted(FILE *out, sqlite3_value *X){
  switch( sqlite3_value_type(X) ){
    case SQLITE_FLOAT: {
      double r1;
      char zBuf[50];
      r1 = sqlite3_value_double(X);
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
      fprintf(out, "%s", zBuf);
      break;
    }
    case SQLITE_INTEGER: {
      fprintf(out, "%lld", sqlite3_value_int64(X));
      break;
    }
    case SQLITE_BLOB: {
      const unsigned char *zBlob = sqlite3_value_blob(X);
      int nBlob = sqlite3_value_bytes(X);
      if( zBlob ){
        int i;
        fprintf(out, "x'");
        for(i=0; i<nBlob; i++){
          fprintf(out, "%02x", zBlob[i]);
        }
        fprintf(out, "'");
      }else{
        /* Could be an OOM, could be a zero-byte blob */
        fprintf(out, "X''");
      }
      break;
    }
    case SQLITE_TEXT: {
      const unsigned char *zArg = sqlite3_value_text(X);
      int i, j;

      if( zArg==0 ){
        fprintf(out, "NULL");
      }else{
        fprintf(out, "'");
        for(i=j=0; zArg[i]; i++){
          if( zArg[i]=='\'' ){
            fprintf(out, "%.*s'", i-j+1, &zArg[j]);
            j = i+1;
          }
        }
        fprintf(out, "%s'", &zArg[j]);
      }
      break;
    }
    case SQLITE_NULL: {
      fprintf(out, "NULL");
      break;
    }
  }
}

/*
** Output SQL that will recreate the aux.zTab table.
*/
static void dump_table(const char *zTab, const char *zAlias){
  int i;                    /* Loop counter */
  int nCol;                 /* Number of result columns */
  sqlite3_stmt *pStmt;      /* SQL statement */
  const char *zSep;         /* Separator string */

  pStmt = db_prepare("SELECT * FROM %s", zTab);
  nCol = sqlite3_column_count(pStmt);
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    printf("INSERT INTO %s VALUES", zAlias);
    zSep = "(";
    for(i=0; i<nCol; i++){
      fprintf(stdout, "%s",zSep);
      printQuoted(stdout, sqlite3_column_value(pStmt,i));
      zSep = ",";
    }
    fprintf(stdout, ");\n");
  }
  sqlite3_finalize(pStmt);
}


/*
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
  printf("Usage: %s [options] DBFILE\n", g.zArgv0);
  printf(







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<







261
262
263
264
265
266
267
















































































268





269

270



271
272
273
274
275
276
277
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    if( sqlite3_column_text(pStmt,3)[0]=='p' && isWithoutRowid ) continue;
    if( sqlite3_column_int(pStmt,4)==0 ) nIndex++;
    analyzeIndex(zTab, (const char*)sqlite3_column_text(pStmt,1));
  }
  sqlite3_finalize(pStmt);
  if( nIndex==0 ){
















































































    printf("INSERT INTO sqlite_stat1 VALUES('%s',NULL,'%lld');\n", zTab, n);





  }

}




/*
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
  printf("Usage: %s [options] DBFILE\n", g.zArgv0);
  printf(
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  if( rc ){
    cmdlineError("cannot open database file \"%s\"", zDb);
  }
  rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
  if( rc || zErrMsg ){
    cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb);
  }
  rc = sqlite3_exec(g.db, "CREATE TEMP TABLE est_stat1(tbl,idx,stat);",
                    0, 0, &zErrMsg);
  if( rc || zErrMsg ){
    cmdlineError("Cannot CREATE TEMP TABLE");
  }
  pStmt = db_prepare("SELECT name FROM sqlite_master"
                     " WHERE type='table' AND rootpage>0"
                     "   AND name NOT LIKE 'sqlite_%%'"
                     " ORDER BY name");
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zName = (const char*)sqlite3_column_text(pStmt, 0);
    analyzeTable(zName);
  }
  sqlite3_finalize(pStmt);
  dump_table("temp.est_stat1","sqlite_stat1");
  sqlite3_close(g.db);
  return 0;
}







|
<
<
<
<









|



320
321
322
323
324
325
326
327




328
329
330
331
332
333
334
335
336
337
338
339
340
  if( rc ){
    cmdlineError("cannot open database file \"%s\"", zDb);
  }
  rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
  if( rc || zErrMsg ){
    cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb);
  }
  printf("ANALYZE sqlite_master;\nDELETE FROM sqlite_stat1;\n");




  pStmt = db_prepare("SELECT name FROM sqlite_master"
                     " WHERE type='table' AND rootpage>0"
                     "   AND name NOT LIKE 'sqlite_%%'"
                     " ORDER BY name");
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zName = (const char*)sqlite3_column_text(pStmt, 0);
    analyzeTable(zName);
  }
  sqlite3_finalize(pStmt);
  printf("ANALYZE sqlite_master;\n");
  sqlite3_close(g.db);
  return 0;
}