Skip to content
Permalink
Browse files

Issue #12: Implement TSQLiteQuery.TableName, and

* free Psqlite3_stmt later, in TSQLiteGridRows.Destroy, not in TSQLiteConnection.Query directly after execution
* move code from TAdoDBQuery.TableName to TDBQuery.TableName, as this is generic SQL parsing which works for all layers (though not so reliable)
  • Loading branch information
ansgarbecker committed Dec 27, 2019
1 parent 91f973c commit efb445928843c2f5373388699df4ce84a1f6bd06
Showing with 71 additions and 25 deletions.
  1. +65 −25 source/dbconnection.pas
  2. +6 −0 source/dbstructures.pas
@@ -578,7 +578,16 @@ TPgConnection = class(TDBConnection)
property LastRawResults: TPGRawResults read FLastRawResults;
end;

TSQLiteRawResults = Array of TGridRows;
TSQLiteConnection = class;
TSQLiteGridRows = class(TGridRows)
private
FConnection: TSQLiteConnection;
public
Statement: Psqlite3_stmt; // Used for querying result structures
constructor Create(AOwner: TSQLiteConnection);
destructor Destroy; override;
end;
TSQLiteRawResults = Array of TSQLiteGridRows;
TSQLiteConnection = class(TDBConnection)
private
FHandle: Psqlite3;
@@ -675,7 +684,7 @@ TDBQuery = class(TComponent)
function Inserted: Boolean;
function SaveModifications: Boolean;
function DatabaseName: String; virtual; abstract;
function TableName: String; virtual; abstract;
function TableName: String; virtual;
function QuotedDbAndTableName: String;
procedure DiscardModifications;
procedure PrepareColumnAttributes;
@@ -732,7 +741,6 @@ TAdoDBQuery = class(TDBQuery)
function IsNull(Column: Integer): Boolean; overload; override;
function HasResult: Boolean; override;
function DatabaseName: String; override;
function TableName: String; override;
end;

TPGQuery = class(TDBQuery)
@@ -759,7 +767,7 @@ TPGQuery = class(TDBQuery)
TSQLiteQuery = class(TDBQuery)
private
FConnection: TSQLiteConnection;
FCurrentResults: TGridRows;
FCurrentResults: TSQLiteGridRows;
FRecNoLocal: Integer;
FResultList: TSQLiteRawResults;
procedure SetRecNo(Value: Int64); override;
@@ -2987,7 +2995,7 @@ procedure TPGConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCate
procedure TSQLiteConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TDBLogCategory=lcSQL);
var
TimerStart: Cardinal;
Rows: TGridRows;
Rows: TSQLiteGridRows;
Row: TGridRow;
Value: TGridValue;
Statement: Psqlite3_stmt;
@@ -3032,7 +3040,7 @@ procedure TSQLiteConnection.Query(SQL: String; DoStoreResult: Boolean=False; Log
FRowsAffected := FLib.sqlite3_changes(FHandle);
FRowsFound := 0;
if DoStoreResult then begin
Rows := TGridRows.Create;
Rows := TSQLiteGridRows.Create(Self);
for i:=0 to FLib.sqlite3_column_count(Statement)-1 do begin
Col := TTableColumn.Create(Self);
Col.Name := DecodeAPIString(FLib.sqlite3_column_name(Statement, i));
@@ -3053,10 +3061,10 @@ procedure TSQLiteConnection.Query(SQL: String; DoStoreResult: Boolean=False; Log
StepStatus := FLib.sqlite3_step(Statement);
end;
FRowsFound := Rows.Count;
Rows.Statement := Statement;
SetLength(FLastRawResults, 1);
FLastRawResults[0] := Rows;
end;
FLib.sqlite3_finalize(Statement);
FResultCount := Length(FLastRawResults);
DetectUSEQuery(SQL);
end;
@@ -6502,7 +6510,7 @@ procedure TSQLiteQuery.Execute(AddResult: Boolean=False; UseRawResult: Integer=-
var
i: Integer;
NumResults: Integer;
LastResult: TGridRows;
LastResult: TSQLiteGridRows;
rx: TRegExpr;
Col: TTableColumn;
begin
@@ -7720,6 +7728,22 @@ function TSQLiteQuery.DatabaseName: String;
end;


function TDBQuery.TableName: String;
var
rx: TRegExpr;
begin
// Untested with joins, compute columns and views
Result := GetTableNameFromSQLEx(SQL, idMixCase);
rx := TRegExpr.Create;
rx.Expression := '\.([^\.]+)$';
if rx.Exec(Result) then
Result := rx.Match[1];
rx.Free;
if Result = '' then
raise EDbError.Create('Could not determine name of table.');
end;


function TMySQLQuery.TableName: String;
var
Field: PMYSQL_FIELD;
@@ -7764,22 +7788,6 @@ function TMySQLQuery.TableName: String;
end;


function TAdoDBQuery.TableName: String;
var
rx: TRegExpr;
begin
// Untested with joins, compute columns and views
Result := GetTableNameFromSQLEx(SQL, idMixCase);
rx := TRegExpr.Create;
rx.Expression := '\.([^\.]+)$';
if rx.Exec(Result) then
Result := rx.Match[1];
rx.Free;
if Result = '' then
raise EDbError.Create('Could not determine name of table.');
end;


function TPGQuery.TableName: String;
var
FieldTypeOID: POid;
@@ -7797,13 +7805,28 @@ function TPGQuery.TableName: String;
end;
if Result <> '' then
Break;
// Todo: what about multiple table names per result?
end;
end;


function TSQLiteQuery.TableName: String;
var
i: Integer;
tblA: AnsiString;
tbl: String;
begin
Result := '';
Result := EmptyStr;
for i:=0 to ColumnCount-1 do begin
tblA := FConnection.Lib.sqlite3_column_table_name(FCurrentResults.Statement, i);
tbl := FConnection.DecodeAPIString(tblA);
if (not Result.IsEmpty) and (not tbl.IsEmpty) and (Result <> tbl) then
raise EDbError.Create(_('More than one table involved.'))
else
Result := tbl;
end;
if Result.IsEmpty then
raise EDbError.Create(_('Could not determine name of table.'));
end;


@@ -7949,6 +7972,23 @@ destructor TGridRows.Destroy;
end;


{ TSQLiteGridRows }

constructor TSQLiteGridRows.Create(AOwner: TSQLiteConnection);
begin
inherited Create;
FConnection := AOwner;
end;

destructor TSQLiteGridRows.Destroy;
begin
FConnection.Log(lcInfo, 'TSQLiteGridRows.Destroy');
FConnection.Lib.sqlite3_finalize(Statement);
inherited;
end;




{ TDBObjectComparer }

@@ -519,6 +519,9 @@ TSQLiteLib = class(TDbLib)
sqlite3_column_count: function(pStmt: Psqlite3_stmt): Integer; cdecl;
sqlite3_column_name: function(pStmt: Psqlite3_stmt; N: Integer): PAnsiChar; cdecl;
sqlite3_column_decltype: function(pStmt: Psqlite3_stmt; N: Integer): PAnsiChar; cdecl;
sqlite3_column_database_name: function(pStmt: Psqlite3_stmt; N: Integer): PAnsiChar; cdecl;
sqlite3_column_table_name: function(pStmt: Psqlite3_stmt; N: Integer): PAnsiChar; cdecl;
sqlite3_column_origin_name: function(pStmt: Psqlite3_stmt; N: Integer): PAnsiChar; cdecl;
private
procedure AssignProcedures; override;
end;
@@ -7794,6 +7797,9 @@ procedure TSQLiteLib.AssignProcedures;
AssignProc(@sqlite3_column_count, 'sqlite3_column_count');
AssignProc(@sqlite3_column_name, 'sqlite3_column_name');
AssignProc(@sqlite3_column_decltype, 'sqlite3_column_decltype');
AssignProc(@sqlite3_column_database_name, 'sqlite3_column_database_name');
AssignProc(@sqlite3_column_table_name, 'sqlite3_column_table_name');
AssignProc(@sqlite3_column_origin_name, 'sqlite3_column_origin_name');
end;


0 comments on commit efb4459

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