Skip to content
Permalink
Browse files

Issue #12: Support query batch fired in one go, and get multiple resu…

…lts per query running. Using pzTail out parameter of sqlite_prepare_v3(), not sqllite_next_stmt(), which returns statements from previously fired queries.
  • Loading branch information
ansgarbecker committed Dec 29, 2019
1 parent 186e4b2 commit 616715987e5e7d9180c6df66261fc4a561ee054c
Showing with 50 additions and 39 deletions.
  1. +36 −38 source/dbconnection.pas
  2. +14 −1 source/dbstructures.pas
@@ -2977,14 +2977,14 @@ procedure TPGConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCate

procedure TSQLiteConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TDBLogCategory=lcSQL);
var
TimerStart: Cardinal;
TimerStart, PrepareFlags: Cardinal;
Rows: TSQLiteGridRows;
Row: TGridRow;
Value: TGridValue;
QueryResult: Psqlite3_stmt;
QueryStatus, StepStatus: Integer;
NativeSQL: AnsiString;
QueryStatus: Integer;
i: Integer;
CurrentSQL, NextSQL: PAnsiChar;
begin
if (FLockedByThread <> nil) and (FLockedByThread.ThreadID <> GetCurrentThreadID) then begin
Log(lcDebug, _('Waiting for running query to finish ...'));
@@ -2998,54 +2998,52 @@ procedure TSQLiteConnection.Query(SQL: String; DoStoreResult: Boolean=False; Log
Ping(True);
Log(LogCategory, SQL);
FLastQuerySQL := SQL;
if IsUnicode then
NativeSQL := UTF8Encode(SQL)
else
NativeSQL := AnsiString(SQL);
CurrentSQL := PAnsiChar(UTF8Encode(SQL));
TimerStart := GetTickCount;
SetLength(FLastRawResults, 0);
FRowsFound := 0;
FRowsAffected := FLib.sqlite3_total_changes(FHandle); // Temporary: substract these later from total num
FWarningCount := 0;

QueryResult := nil;
QueryStatus := FLib.sqlite3_prepare_v2(FHandle, PAnsiChar(NativeSQL), -1, QueryResult, nil);
FLastQueryDuration := GetTickCount - TimerStart;
FLastQueryNetworkDuration := 0;
NextSQL := nil;
PrepareFlags := SQLITE_PREPARE_PERSISTENT;

if QueryStatus <> SQLITE_OK then begin
FRowsAffected := 0;
Log(lcError, GetLastErrorMsg);
raise EDbError.Create(GetLastErrorMsg);
end else begin
while True do begin
QueryStatus := FLib.sqlite3_prepare_v3(FHandle, CurrentSQL, -1, PrepareFlags, QueryResult, NextSQL);
FLastQueryDuration := GetTickCount - TimerStart;
FLastQueryNetworkDuration := 0;

if QueryStatus <> SQLITE_OK then begin
FRowsAffected := 0;
Log(lcError, GetLastErrorMsg);
raise EDbError.Create(GetLastErrorMsg);
end;
FRowsAffected := FLib.sqlite3_total_changes(FHandle) - FRowsAffected;
FRowsFound := 0;
QueryResult := FLib.sqlite3_next_stmt(FHandle, nil);
while QueryResult <> nil do begin
if DoStoreResult then begin
Rows := TSQLiteGridRows.Create(Self);
StepStatus := FLib.sqlite3_step(QueryResult);
while StepStatus = SQLITE_ROW do begin
Row := TGridRow.Create;
for i:=0 to FLib.sqlite3_column_count(QueryResult)-1 do begin
Value := TGridValue.Create;
Value.OldText := DecodeAPIString(FLib.sqlite3_column_text(QueryResult, i));
Value.OldIsNull := FLib.sqlite3_column_text(QueryResult, i) = nil;
Row.Add(Value);
end;
Rows.Add(Row);
StepStatus := FLib.sqlite3_step(QueryResult);
if DoStoreResult then begin
Rows := TSQLiteGridRows.Create(Self);
while FLib.sqlite3_step(QueryResult) = SQLITE_ROW do begin
Row := TGridRow.Create;
for i:=0 to FLib.sqlite3_column_count(QueryResult)-1 do begin
Value := TGridValue.Create;
Value.OldText := DecodeAPIString(FLib.sqlite3_column_text(QueryResult, i));
Value.OldIsNull := FLib.sqlite3_column_text(QueryResult, i) = nil;
Row.Add(Value);
end;
Inc(FRowsFound, Rows.Count);
Rows.Statement := QueryResult;
SetLength(FLastRawResults, Length(FLastRawResults)+1);
FLastRawResults[Length(FLastRawResults)-1] := Rows;
end else begin
FLib.sqlite3_finalize(QueryResult);
Rows.Add(Row);
end;
DetectUSEQuery(SQL);
QueryResult := FLib.sqlite3_next_stmt(FHandle, QueryResult);
Inc(FRowsFound, Rows.Count);
Rows.Statement := QueryResult;
SetLength(FLastRawResults, Length(FLastRawResults)+1);
FLastRawResults[Length(FLastRawResults)-1] := Rows;
end else begin
FLib.sqlite3_finalize(QueryResult);
end;
DetectUSEQuery(SQL);
CurrentSQL := NextSQL;
if Trim(CurrentSQL) = '' then
Break;
end;
FLastQueryNetworkDuration := GetTickCount - TimerStart;
end;
@@ -114,6 +114,17 @@ interface
SQLITE_ROW = 100; // sqlite3_step() has another row ready
SQLITE_DONE = 101; // sqlite3_step() has finished executing

{ SQLite Flags
These constants define various flags that can be passed into
"prepFlags" parameter of the [sqlite3_prepare_v3()] and
[sqlite3_prepare16_v3()] interfaces.
New flags may be added in future releases of SQLite.
}
SQLITE_PREPARE_PERSISTENT = $01; // prepared statement will be retained for a long time and probably reused many times
SQLITE_PREPARE_NORMALIZE = $02; // no-op
SQLITE_PREPARE_NO_VTAB = $04; // return an error (error code SQLITE_ERROR) if the statement uses any virtual tables


type
PUSED_MEM=^USED_MEM;
@@ -510,7 +521,8 @@ TSQLiteLib = class(TDbLib)
sqlite3_close: function(ppDb: Psqlite3): Integer; cdecl;
sqlite3_errmsg: function(ppDb: Psqlite3): PAnsiChar; cdecl;
sqlite3_errcode: function(ppDb: Psqlite3): Integer; cdecl;
sqlite3_prepare_v2: function(ppDb: Psqlite3; zSql: PAnsiChar; nByte: Integer; var ppStmt: Psqlite3_stmt; pzTail: PAnsiChar): Integer; cdecl;
sqlite3_prepare_v2: function(ppDb: Psqlite3; zSql: PAnsiChar; nByte: Integer; var ppStmt: Psqlite3_stmt; var pzTail: PAnsiChar): Integer; cdecl;
sqlite3_prepare_v3: function(ppDb: Psqlite3; zSql: PAnsiChar; nByte: Integer; prepFlags: Cardinal; var ppStmt: Psqlite3_stmt; var pzTail: PAnsiChar): Integer; cdecl;
sqlite3_exec: function(ppDb: Psqlite3; sql: PAnsiChar; callback: Integer; callvack_arg: Pointer; errmsg: PAnsiChar): Integer; cdecl;
sqlite3_finalize: function(pStmt: Psqlite3_stmt): Integer; cdecl;
sqlite3_step: function(pStmt: Psqlite3_stmt): Integer; cdecl;
@@ -7790,6 +7802,7 @@ procedure TSQLiteLib.AssignProcedures;
AssignProc(@sqlite3_errmsg, 'sqlite3_errmsg');
AssignProc(@sqlite3_errcode, 'sqlite3_errcode');
AssignProc(@sqlite3_prepare_v2, 'sqlite3_prepare_v2');
AssignProc(@sqlite3_prepare_v3, 'sqlite3_prepare_v3');
AssignProc(@sqlite3_exec, 'sqlite3_exec');
AssignProc(@sqlite3_finalize, 'sqlite3_finalize');
AssignProc(@sqlite3_step, 'sqlite3_step');

0 comments on commit 6167159

Please sign in to comment.
You can’t perform that action at this time.