** If compiled statement pSql appears to be an EXPLAIN statement, allocate ** and populate the ShellState.aiIndent[] array with the number of ** spaces each opcode should be indented before it is output. ** ** The indenting rules are: ** ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent ** all opcodes that occur between the p2 jump destination and the opcode ** i
| 18390 | ** and "Goto" by 2 spaces. |
| 18391 | */ |
| 18392 | static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ |
| 18393 | const char *zSql; /* The text of the SQL statement */ |
| 18394 | const char *z; /* Used to check if this is an EXPLAIN */ |
| 18395 | int *abYield = 0; /* True if op is an OP_Yield */ |
| 18396 | int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ |
| 18397 | int iOp; /* Index of operation in p->aiIndent[] */ |
| 18398 | |
| 18399 | const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", |
| 18400 | "Return", 0 }; |
| 18401 | const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", |
| 18402 | "Rewind", 0 }; |
| 18403 | const char *azGoto[] = { "Goto", 0 }; |
| 18404 | |
| 18405 | /* Try to figure out if this is really an EXPLAIN statement. If this |
| 18406 | ** cannot be verified, return early. */ |
| 18407 | if( sqlite3_column_count(pSql)!=8 ){ |
| 18408 | p->cMode = p->mode; |
| 18409 | return; |
| 18410 | } |
| 18411 | zSql = sqlite3_sql(pSql); |
| 18412 | if( zSql==0 ) return; |
| 18413 | for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); |
| 18414 | if( sqlite3_strnicmp(z, "explain", 7) ){ |
| 18415 | p->cMode = p->mode; |
| 18416 | return; |
| 18417 | } |
| 18418 | |
| 18419 | for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ |
| 18420 | int i; |
| 18421 | int iAddr = sqlite3_column_int(pSql, 0); |
| 18422 | const char *zOp = (const char*)sqlite3_column_text(pSql, 1); |
| 18423 | |
| 18424 | /* Set p2 to the P2 field of the current opcode. Then, assuming that |
| 18425 | ** p2 is an instruction address, set variable p2op to the index of that |
| 18426 | ** instruction in the aiIndent[] array. p2 and p2op may be different if |
| 18427 | ** the current instruction is part of a sub-program generated by an |
| 18428 | ** SQL trigger or foreign key. */ |
| 18429 | int p2 = sqlite3_column_int(pSql, 3); |
| 18430 | int p2op = (p2 + (iOp-iAddr)); |
| 18431 | |
| 18432 | /* Grow the p->aiIndent array as required */ |
| 18433 | if( iOp>=nAlloc ){ |
| 18434 | if( iOp==0 ){ |
| 18435 | /* Do further verfication that this is explain output. Abort if |
| 18436 | ** it is not */ |
| 18437 | static const char *explainCols[] = { |
| 18438 | "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; |
| 18439 | int jj; |
| 18440 | for(jj=0; jj<ArraySize(explainCols); jj++){ |
| 18441 | if( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){ |
| 18442 | p->cMode = p->mode; |
| 18443 | sqlite3_reset(pSql); |
| 18444 | return; |
| 18445 | } |
| 18446 | } |
| 18447 | } |
| 18448 | nAlloc += 100; |
| 18449 | p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); |
no test coverage detected