[yunqa.de] Re: SQLite metadata

  • From: Delphi Inspiration <delphi@xxxxxxxx>
  • To: yunqa@xxxxxxxxxxxxx
  • Date: Wed, 03 Jun 2009 17:42:01 +0200

At 12:50 01.06.2009, Radovan Antloga wrote:

>I did add also that this can't be reproduced with sqlite3.exe.

I investigated further and found that sqlite3.exe encounters the same problem 
but works around it by calling sqlite3_prepare() a 2nd time after 
SQLITE_SCHEMA. I have appended http://www.sqlite.org/cvstrac/tktview?tn=3890 
accordingly.

For DISQLite3 and Delphi, a similar workaround might look like this:

  Retries := 0;
  repeat
    Inc(Retries);
    e := sqlite3_prepare(Db2, 'select a from t', -1, @Stmt, nil);
  until (e <> SQLITE_SCHEMA) or (Retries > 1);

The full source code is in the attach.

Ralf  
{ Visit the DISQLite3 Internet site for latest information and updates:

    http://www.yunqa.de/delphi/

  Copyright (c) 2009 Ralf Junker, The Delphi Inspiration <delphi@xxxxxxxx>

------------------------------------------------------------------------------ }

program DISQLite3_Multiple_Connections;

{$APPTYPE CONSOLE}
{$I DI.inc}
{$I DISQLite3.inc}

uses
  {$IFDEF FastMM}FastMM4, {$ENDIF}Windows, DISQLite3Api;

//------------------------------------------------------------------------------

procedure r(const DB: sqlite3; const SQL: AnsiString);
var
  Stmt: sqlite3_stmt;
begin
  sqlite3_check(sqlite3_prepare(DB, PAnsiChar(SQL), -1, @Stmt, nil), DB);

  while sqlite3_check(sqlite3_step(Stmt), DB) = SQLITE_ROW do
    WriteLn(sqlite3_column_str(Stmt, 0));

  sqlite3_check(sqlite3_finalize(Stmt), DB);
end;

var
  e, Retries: Integer;
  Db1, Db2: sqlite3;
  Stmt: sqlite3_stmt;
begin
  DeleteFile('test.db3');

  { Open 2 database connections. }

  sqlite3_check(sqlite3_open('test.db3', @Db1));
  sqlite3_check(sqlite3_open('test.db3', @Db2));

  sqlite3_exec_fast(Db2, 'pragma synchronous=full');

  { Create table in connection 1. }

  sqlite3_exec_fast(Db1, 'create table t(a)');
  sqlite3_exec_fast(Db1, 'insert into t values (1)');
  sqlite3_exec_fast(Db1, 'insert into t values (2)');

  { Use connection 2 to read from table created in connection 1.

    Retry to prepare the statement if the initial call to sqlite3_prepare() or
    sqlite3_prepare_v2() returns SQLITE_SCHEMA. }
  Retries := 0;
  repeat
    Inc(Retries);
    e := sqlite3_prepare(Db2, 'select a from t', -1, @Stmt, nil);
  until (e <> SQLITE_SCHEMA) or (Retries > 1);
  sqlite3_check(e, Db2);

  while sqlite3_check(sqlite3_step(Stmt), Db2) = SQLITE_ROW do
    WriteLn(sqlite3_column_str(Stmt, 0));

    sqlite3_check(sqlite3_finalize(Stmt), Db2);

  { Cleanup. }

  sqlite3_check(sqlite3_close(Db2), Db2);
  sqlite3_check(sqlite3_close(Db1), Db1);

  sqlite3_shutdown;

  WriteLn;
  WriteLn('Done - Press ENTER to Exit');
  ReadLn;
end.

Other related posts: