"Dave Gierok" <[EMAIL PROTECTED]> wrote:
> I am developing a game on Xbox360 using Sqlite for a lot of our data
> manipulation.

That's good to know.  I'll be shortly adding a Microsoft logo
to the image of companies and projects using SQLite at

   http://www.sqlite.org/google-talk-slides/logos4.gif

:-)

> We use the ':memory:' functionality to create our DB in
> RAM, because we need our DB manipulations to be very fast - we can't
> afford for our queries to cause seeks/loads on the DVD.  
> 
> This works very well for us with one exception:  It takes a long time to
> load the DB.  Since we need the DB to be in memory, we create an empty
> ':memory:' DB, then load up a file which contains all the SQL (CREATE
> TABLE, INSERT INTO) we need to create our tables and execute them on the
> memory-DB.  This process currently takes 10 seconds (all running the SQL
> statements to create the tables), which is not acceptable for our game.
> 

The code below should do what you need.  First create your :memory:
database.  Then open the file that contains the initialization
database.  Then read a chunk of the file and write that same chunk
into the :memory: database by calling sqlite3_raw_write().

The code below messes with internal data structures of SQLite and
is not guaranteed to work in future SQLite releases.  So beware.


/*
** This routine is called to write data directly into the database image
** (presumably taken from a database file created externally).
**
** The database from which the supplied data is taken must have a page-size
** equal to the value of the SQLITE_DEFAULT_PAGE_SIZE macro this file is
** compiled with.
*/
int sqlite3_raw_write(
  sqlite3 *db, 
  int nData, 
  int iOffset, 
  unsigned const char *zData
){
  Pager *pPager;
  int pageSize;              /* Copy of pPager->pageSize */
  int psAligned;             /* Copy of pPager->psAligned */
  int n;                     /* Remaining bytes to copy into database pages */
  unsigned const char *z;    /* Bytes to copy into database pages */
  int iPage;                 /* Page number to copy into */
  int iOff;                  /* Offset on iPage to write to */
  int rc = SQLITE_OK;        /* Offset on iPage to write to */
  unsigned char *p1 = 0;     /* First page of database */

  assert( db );
  assert( nData>=0 );
  assert( iOffset>=0 );
  assert( db->aDb[0].pBt );
  assert( zData || nData==0 );

  pPager = sqlite3BtreePager(db->aDb[0].pBt);
  psAligned = pPager->psAligned;
  pageSize = pPager->psAligned;
  z = zData;
  n = nData;

  /* This routine may not be used if any statements or a transaction are
  ** currently active. If this is not the case and we can proceed, grab a
  ** reference to page 1 and hold it until the end of this function so that
  ** the transaction is not rolled back because the page reference count 
  ** reaches zero.
  */
  if( pPager->nRef>1 ){
    rc = SQLITE_MISUSE;
  }else{
    rc = sqlite3pager_get(pPager, 1, (void **)&p1);
  }

  iPage = (iOffset / psAligned) + 1;
  iOff = (iOffset % psAligned);
  while( n>0 && rc==SQLITE_OK ){
    int bytes;                       /* Number of bytes to write */
    unsigned char *p = 0;            /* Page iPage */
    bytes = pageSize-iOff;
    bytes = (bytes<n)?bytes:n;

    /* Retrieve the page, set it to writable and copy the data to it. The
    ** first sqlite3pager_write() call starts a new transaction, which is
    ** committed at the end of this routine.
    */
    if( SQLITE_OK==(rc=sqlite3pager_get(pPager, iPage, (void **)&p)) &&
        SQLITE_OK==(rc=sqlite3pager_write(p))
    ){
      memcpy(&p[iOff], z, bytes);
    }
    if( p ){
      sqlite3pager_unref(p);
    }

    bytes += (psAligned-pageSize);
    n -= bytes;
    z += bytes;
    iOff = 0;
    iPage++;
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3pager_commit(pPager);
  }
  if( p1 ){
    sqlite3pager_unref(p1);
  }
  sqlite3Error(db, rc, 0);
  return sqlite3ApiExit(db, rc);
}

--
D. Richard Hipp   <[EMAIL PROTECTED]>

Reply via email to