/ Check-in [ffda1d1e]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add extra (somewhat inefficient) trace callbacks for triggers if SQLITE_TRACE_TRIGGER is defined.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trigger-trace
Files: files | file ages | folders
SHA1: ffda1d1e1c858abd02f0c07b906cfac5ad075498
User & Date: dan 2017-01-21 15:58:42
Context
2017-01-21
16:21
Fix problems in the previous commit. Leaf check-in: 74ad80eb user: dan tags: trigger-trace
15:58
Add extra (somewhat inefficient) trace callbacks for triggers if SQLITE_TRACE_TRIGGER is defined. check-in: ffda1d1e user: dan tags: trigger-trace
15:55
In the kvtest.c test utility, reuse the buffer into which blobs are read, rather than reallocating it for each row. This is a closer match to how other test programs work, and thus provides a better comparison. check-in: 0d1ad13a user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/shell.c.

610
611
612
613
614
615
616

617
618
619
620
621
622
623
....
1992
1993
1994
1995
1996
1997
1998






1999
2000
2001
2002
2003
2004
2005
....
5334
5335
5336
5337
5338
5339
5340










5341
5342
5343
5344
5345
5346
5347
typedef struct ShellState ShellState;
struct ShellState {
  sqlite3 *db;           /* The database */
  int echoOn;            /* True to echo input commands */
  int autoExplain;       /* Automatically turn on .explain mode */
  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  int statsOn;           /* True to display memory stats before each finalize */

  int scanstatsOn;       /* True to display scan stats before each finalize */
  int countChanges;      /* True to display change counts */
  int backslashOn;       /* Resolve C-style \x escapes in SQL input text */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  FILE *traceOut;        /* Output for sqlite3_trace() */
................................................................................
      exec_prepared_stmt(pArg, pStmt, xCallback);
      explain_data_delete(pArg);

      /* print usage stats if stats on */
      if( pArg && pArg->statsOn ){
        display_stats(db, pArg, 0);
      }







      /* print loop-counters if required */
      if( pArg && pArg->scanstatsOn ){
        display_scanstats(db, pArg);
      }

      /* Finalize the statement just executed. If this fails, save a
................................................................................
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
        utf8_printf(p->out, "%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
  }else











#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
  }else
#endif








>







 







>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
....
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
....
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
typedef struct ShellState ShellState;
struct ShellState {
  sqlite3 *db;           /* The database */
  int echoOn;            /* True to echo input commands */
  int autoExplain;       /* Automatically turn on .explain mode */
  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  int statsOn;           /* True to display memory stats before each finalize */
  int vmstepsOn;         /* Display VM steps before each finalize */
  int scanstatsOn;       /* True to display scan stats before each finalize */
  int countChanges;      /* True to display change counts */
  int backslashOn;       /* Resolve C-style \x escapes in SQL input text */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  FILE *traceOut;        /* Output for sqlite3_trace() */
................................................................................
      exec_prepared_stmt(pArg, pStmt, xCallback);
      explain_data_delete(pArg);

      /* print usage stats if stats on */
      if( pArg && pArg->statsOn ){
        display_stats(db, pArg, 0);
      }

      if( pArg && pArg->vmstepsOn && pStmt ){
        int iCur = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_VM_STEP, 0);
        FILE *out = pArg->traceOut ? pArg->traceOut : pArg->out;
        raw_printf(out, "VM steps: %d\n", iCur);
      }

      /* print loop-counters if required */
      if( pArg && pArg->scanstatsOn ){
        display_scanstats(db, pArg);
      }

      /* Finalize the statement just executed. If this fails, save a
................................................................................
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
        utf8_printf(p->out, "%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
  }else

  if( c=='v' && strncmp(azArg[0], "vmsteps", n)==0 ){
    if( nArg==2 ){
      p->vmstepsOn = booleanValue(azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .vmsteps ?on|off?\n");
      rc = 1;
    }
  }else


#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
  }else
#endif

Changes to src/vdbe.c.

956
957
958
959
960
961
962





















963
964
965
966
967
968
969
....
5829
5830
5831
5832
5833
5834
5835




5836
5837
5838
5839
5840
5841
5842
....
6885
6886
6887
6888
6889
6890
6891














6892
6893
6894
6895
6896
6897
6898
  if( pOp->p1==SQLITE_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite3VdbeSetChanges(db, p->nChange);
    pcx = sqlite3VdbeFrameRestore(pFrame);





















    lastRowid = db->lastRowid;
    if( pOp->p2==OE_Ignore ){
      /* Instruction pcx is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
................................................................................
    pFrame->nCursor = p->nCursor;
    pFrame->aOp = p->aOp;
    pFrame->nOp = p->nOp;
    pFrame->token = pProgram->token;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    pFrame->anExec = p->anExec;
#endif





    pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
    for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
      pMem->flags = MEM_Undefined;
      pMem->db = db;
    }
  }else{
................................................................................
#ifndef SQLITE_OMIT_DEPRECATED
    if( db->mTrace & SQLITE_TRACE_LEGACY ){
      void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace;
      char *z = sqlite3VdbeExpandSql(p, zTrace);
      x(db->pTraceArg, z);
      sqlite3_free(z);
    }else














#endif
    {
      (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
    }
  }
#ifdef SQLITE_USE_FCNTL_TRACE
  zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
....
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
....
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
  if( pOp->p1==SQLITE_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite3VdbeSetChanges(db, p->nChange);
    pcx = sqlite3VdbeFrameRestore(pFrame);
#ifdef SQLITE_TRACE_TRIGGER
    if( (db->mTrace & SQLITE_TRACE_STMT) && aOp[0].p4.z ){
      int nNest = 0;
      VdbeFrame *pF;
      int nTotal = nVmStep - pFrame->nVmStep;
      char *zTrace;
      assert( db->xTrace );
      for(pF=p->pFrame; pF; pF=pF->pParent) nNest++;
      zTrace = sqlite3_mprintf("%.*s%s completed (VM steps: total=%d self=%d)", 
          nNest, "                                                    :",
          aOp[0].p4.z, nTotal, nVmStep - pFrame->nVmStepAdj
      );
      if( zTrace ){
        (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, 0, zTrace);
        sqlite3_free(zTrace);
      }
      if( p->pFrame ){
        p->pFrame->nVmStepAdj += nTotal;
      }
    }
#endif
    lastRowid = db->lastRowid;
    if( pOp->p2==OE_Ignore ){
      /* Instruction pcx is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
................................................................................
    pFrame->nCursor = p->nCursor;
    pFrame->aOp = p->aOp;
    pFrame->nOp = p->nOp;
    pFrame->token = pProgram->token;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    pFrame->anExec = p->anExec;
#endif
#ifdef SQLITE_TRACE_TRIGGER
    pFrame->nVmStep = nVmStep;
    pFrame->nVmStepAdj = nVmStep;
#endif

    pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
    for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
      pMem->flags = MEM_Undefined;
      pMem->db = db;
    }
  }else{
................................................................................
#ifndef SQLITE_OMIT_DEPRECATED
    if( db->mTrace & SQLITE_TRACE_LEGACY ){
      void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace;
      char *z = sqlite3VdbeExpandSql(p, zTrace);
      x(db->pTraceArg, z);
      sqlite3_free(z);
    }else
#endif
#ifdef SQLITE_TRACE_TRIGGER
    if( p->pFrame ){
      int nNest = -1;
      VdbeFrame *pFrame;
      for(pFrame=p->pFrame; pFrame; pFrame=pFrame->pParent) nNest++;
      zTrace = sqlite3_mprintf("%.*s%s",
          nNest, "                                                    :", zTrace
      );
      if( zTrace ){
        (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
        sqlite3_free(zTrace);
      }
    }else
#endif
    {
      (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
    }
  }
#ifdef SQLITE_USE_FCNTL_TRACE
  zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);

Changes to src/vdbeInt.h.

171
172
173
174
175
176
177




178
179
180
181
182
183
184
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChange)     */
  int nDbChange;          /* Value of db->nChange */




};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,







>
>
>
>







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChange)     */
  int nDbChange;          /* Value of db->nChange */
#ifdef SQLITE_TRACE_TRIGGER
  int nVmStep;            /* Value of nVmStep at start of program */
  int nVmStepAdj;         /* Adjusted for nested programs */
#endif
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,