Small. Fast. Reliable.
Choose any three.
*** 18,26 ****
      int sqlite_compile(
        sqlite *db,           /* An open database */
        const char *zSQL,     /* The SQL to be compiled */
!       char **azErrMsg,      /* Error message written here */
!       sqlitevm **pVm,       /* Virtual machine written here */
!       const char **pzTail   /* Part of zSQL not compiled */
      );
  
  The routine above compiles the first SQL statement out of zSQL
--- 18,26 ----
      int sqlite_compile(
        sqlite *db,           /* An open database */
        const char *zSQL,     /* The SQL to be compiled */
!       const char **pzTail,  /* OUT: Part of zSQL not compiled */
!       sqlite_vm **pVm,      /* OUT: Virtual machine written here */
!       char **pzErrMsg       /* OUT: Error message written here */
      );
  
  The routine above compiles the first SQL statement out of zSQL
***************
*** 33,78 ****
  
      const char *z = zOrigSql;
      while( z && z[0] ){
!       sqlite_compile(db, z, 0, &pVm, &z);
        /* Deal with pVm */
      }
  
  A virtual machine is allocated and written into *pVm.  The virtual
! machine is opaque - users cannot use the internals of the sqlitevm
! structure.  The only thing you are allowed to do with an sqlitevm
  is pass it to other API routines.
  
  Run a VM something like this:
  
!     while( sqlitevm_step(pVm) ){
        /* Do something with a row of data */
      }
!     rc = sqlitevm_finalize(pVm, &zErrMsg);
  
! The sqlitevm_step(pVm) runs the virtual machine until it generates
! a new row of data or until it finishes.  After the VM finishes, call
! sqlitevm_finalize(pVm) to deallocate it.  The sqlitevm_finalize()
  returns the result code (ex: SQLITE_OK, SQLITE_BUSY, SQLITE_FULL, etc)
  and also sets the error message string if appropriate.
  
! Within the VM run loop you can access data as follows:
  
!     while( sqlitevm_step(pVm) ){
        int i;
!       for(i=0; i<sqlitevm_column_count(pVm); i++){
          printf("%s(type %s) = %s\n",
!           sqlitevm_column_name(pVm, i),
!           sqlitevm_column_type(pVm, i),
!           sqlitevm_column_data(pVm, i));
        }
      }
      rc = sqlitevm_finalize(pVm, &zErrMsg);
  
! The sqlitevm_column_count() routine returns the number of columns
! in the result row.  sqlitevm_column_name() and sqlitevm_column_type()
! return the name and datatype of the column.  sqlitevm_column_data()
! returns the text data for the column.  All of these sqlite_column
! functions might be implemented as macros for speed.
! sqlitevm_column_data() will return NULL for NULL data.  If the
! 2nd argument is out of range, unpreditable things will happen.
! (Perhaps a segfault.)
--- 33,84 ----
  
      const char *z = zOrigSql;
      while( z && z[0] ){
!       sqlite_compile(db, z, &z, &pVm, 0);
        /* Deal with pVm */
      }
  
  A virtual machine is allocated and written into *pVm.  The virtual
! machine is opaque - users cannot use the internals of the sqlite_vm
! structure.  The only thing you are allowed to do with an sqlite_vm
  is pass it to other API routines.
  
  Run a VM something like this:
  
!     while( sqlite_step(pVm, &n, &azValue, &azColName)==SQLITE_ROW ){
        /* Do something with a row of data */
      }
!     rc = sqlite_finalize(pVm, &zErrMsg);
  
! The sqlite_step() call runs the virtual machine until it generates
! a new row of data, encounters an error, or until it finishes.
! After the VM finishes, call
! sqlite_finalize(pVm) to deallocate it.  The sqlite_finalize()
  returns the result code (ex: SQLITE_OK, SQLITE_BUSY, SQLITE_FULL, etc)
  and also sets the error message string if appropriate.
  
! Information about a single row of the result is written into
! variables that are passed by address into sqlite_step().  The
! variable "n" is filled with the number of columns in a single
! row of the result.  azValue is filled with a pointer to an array
! of pointers to strings - one string for each result.  NULL values
! in the result are represented by NULL pointers.  This works just
! like the azValues parameter to an sqlite_exec() callback.  The
! azColName variable is filled with a pointer to an array of pointers
! to strings.  The first N strings contain column names and the second
! ground of N strings contain column types.  The column types are
! always reported, regardless of the setting of the SHOW_DATATYPES
! pragma.
  
!     while( sqlite_step(pVm, &n, &azValue, &azColName) ){
        int i;
!       for(i=0; i<n; i++){
          printf("%s(type %s) = %s\n",
!           azColName[i], azColName[i+n], azValue[i]);
        }
      }
      rc = sqlitevm_finalize(pVm, &zErrMsg);
  
! The non-callback API has now been implemented and tested.  For
! additional information see the comments in 
! {link: getfile?f=sqlite/src/sqlite.h.in sqlite.h.in} or read the
! latest C/C++ interface documentation.