disqlite3dataset.pas
来自「DELPHI 访问SQLITE3 数据库的VCL控件」· PAS 代码 · 共 1,786 行 · 第 1/4 页
PAS
1,786 行
Col.ColumnDeclaration := '';
Col.ColumnOriginName := '';
Col.ColumnTableName := '';
Col.ColumnDatabaseName := '';
sqlite3_finalize_cell16(Data);
end;
FreeMem(FRowBuffer);
FRowBuffer := nil;
FColumnCount := 0;
end;
function TDISqlite3UniDirQuery.GetUpdateSql(const AUpdateKind: TUpdateKind): WideString;
var
Stmt: TDISQLite3Statement;
begin
Stmt := FUpdateStatements[AUpdateKind];
if Assigned(Stmt) then
Result := Stmt.SQL16
else
Result := '';
end;
function TDISqlite3UniDirQuery.GetSelectSQL: WideString;
begin
Result := FSelectStatement.SQL16;
end;
procedure TDISqlite3UniDirQuery.SetUpdateSql(const AUpdateKind: TUpdateKind; const AValue: WideString);
var
Stmt: TDISQLite3Statement;
begin
Stmt := FUpdateStatements[AUpdateKind];
if Assigned(Stmt) then
if AValue <> '' then
begin
Stmt.Active := False;
Stmt.SQL16 := AValue;
end
else
begin
FUpdateStatements[AUpdateKind] := nil;
Stmt.Free;
end
else
if AValue <> '' then
begin
Stmt := TDISQLite3Statement.Create;
Stmt.SQL16 := AValue;
Stmt.Database := Database;
FUpdateStatements[AUpdateKind] := Stmt;
end;
end;
procedure TDISqlite3UniDirQuery.SetSelectSQL(const AValue: WideString);
begin
FSelectStatement.SQL16 := AValue;
end;
procedure TDISqlite3UniDirQuery.InternalOpen;
begin
FSelectStatement.Active := True;
InternalInitFieldDefs;
if DefaultFields then
CreateFields;
BindFields(True);
end;
procedure TDISqlite3UniDirQuery.InternalClose;
var
uk: TUpdateKind;
Stmt: TDISQLite3Statement;
begin
FSelectStatement.Active := False;
for uk := Low(TUpdateKind) to High(TUpdateKind) do
begin
Stmt := FUpdateStatements[uk];
if Assigned(Stmt) then
Stmt.Active := False;
end;
FreeRowBuffer;
if DefaultFields then
DestroyFields;
end;
function TDISqlite3UniDirQuery.IsCursorOpen: Boolean;
begin
Result := FSelectStatement.Active;
end;
procedure TDISqlite3UniDirQuery.InternalInitFieldDefs;
function IsKey(
const ADatabaseName: WideString;
const ATableName: WideString;
const AOriginName: WideString): Boolean;
var
SQL: WideString;
Stmt, Stmt2: TDISQLite3Statement;
begin
Result :=
(ADatabaseName <> '') and
(ATableName <> '') and
(AOriginName <> '');
if not Result then Exit;
Result := AOriginName = 'rowid';
if Result then Exit;
Stmt := TDISQLite3Statement.Create;
Stmt.Database := Database;
try
Stmt.SQL16 := sqlite3_pragma_database16(ADatabaseName) + '"table_info"(' + DISQLite3Api.QuotedStr16(ATableName) + ')';
Stmt.Active := True;
try
while Stmt.Step = SQLITE_ROW do
begin
Result :=
(Stmt.Column_Str16(1) = AOriginName) and
(Stmt.Column_Int(5) = 1);
if Result then Break;
end;
finally
Stmt.Active := False;
end;
if not Result then
begin
SQL := sqlite3_pragma_database16(ADatabaseName) + '"index_list"(' + DISQLite3Api.QuotedStr16(ATableName) + ')';
Stmt.SQL16 := SQL;
Stmt.Active := True;
Stmt2 := TDISQLite3Statement.Create;
Stmt2.Database := Database;
try
while Stmt.Step = SQLITE_ROW do
if Stmt.Column_Int(2) = 1 then
begin
SQL := sqlite3_pragma_database16(ADatabaseName) + '"index_info"(' + DISQLite3Api.QuotedStr16(Stmt.Column_Str16(1)) + ')';
Stmt2.Close;
Stmt2.SQL16 := SQL;
Stmt2.Open;
while Stmt2.Step = SQLITE_ROW do
begin
Result := Stmt2.Column_Str16(2) = AOriginName;
if Result then Break;
end;
if Result then Break;
end;
finally
Stmt2.Free;
end;
end;
finally
Stmt.Free;
end;
end;
var
ColumnIdx, i, t: Integer;
f: TField;
FDataType: TFieldType;
FSize: Integer;
ColumnDeclaration, FieldName, UniqueFieldName: WideString;
NewFieldDef: TFieldDef;
Stepped, StepResult: Boolean;
Stmt: TDISQLite3Statement;
begin
FieldDefs.Clear;
if not Assigned(FRowBuffer) then
begin
Stmt := TDISQLite3Statement.Create;
try
Stmt.Assign(FSelectStatement);
Stmt.Active := True;
Stepped := False; StepResult := False;
AllocRowBuffer(Stmt.Column_Count);
for ColumnIdx := 0 to FColumnCount - 1 do
begin
ColumnDeclaration := Stmt.Column_DeclType16(ColumnIdx);
if ColumnDeclaration <> '' then
begin
t := SQLITE3_AFFINITY_TO_TYPE[sqlite3_affinity16(ColumnDeclaration)];
end
else
begin
if not Stepped then
begin
Stepped := True;
try
StepResult := Stmt.Step = SQLITE_ROW;
except
StepResult := False;
end;
end;
if StepResult then
begin
t := Stmt.Column_Type(ColumnIdx);
if t = SQLITE_NULL then
t := SQLITE_TEXT;
end
else
t := SQLITE_TEXT;
end;
with FRowBuffer^[ColumnIdx] do
begin
Col.ColumnName := Stmt.Column_Name16(ColumnIdx);
Col.ColumnType := t;
Col.ColumnDeclaration := ColumnDeclaration;
Col.ColumnOriginName := Stmt.Column_Origin_Name16(ColumnIdx);
Col.ColumnTableName := Stmt.Column_Table_Name16(ColumnIdx);
Col.ColumnDatabaseName := Stmt.Column_database_Name16(ColumnIdx);
Col.ColumnIsKey := IsKey(Col.ColumnDatabaseName, Col.ColumnTableName, Col.ColumnOriginName);
end;
end;
finally
Stmt.Free;
end;
end;
for ColumnIdx := 0 to FColumnCount - 1 do
with FRowBuffer^[ColumnIdx] do
begin
i := 0;
FieldName := Col.ColumnName;
UniqueFieldName := FieldName;
while FieldDefs.IndexOf(UniqueFieldName) >= 0 do
begin
Inc(i);
UniqueFieldName := Format('%s_%d', [FieldName, i]);
end;
f := FindField(UniqueFieldName);
if Assigned(f) then
begin
FDataType := f.DataType;
FSize := f.Size;
end
else
begin
FSize := 0;
case Col.ColumnType of
SQLITE_INTEGER:
begin
FDataType := ftLargeInt;
end;
SQLITE_FLOAT:
begin
FDataType := ftFloat;
end;
SQLITE_BLOB:
begin
FDataType := ftBlob;
end;
SQLITE_TEXT:
begin
FDataType := ftWideString;
FSize := 20;
end;
else
Assert(False, 'Invalid ColumnType');
FDataType := ftUnknown;
end;
end;
NewFieldDef := FieldDefs.AddFieldDef;
try
NewFieldDef.Name := UniqueFieldName;
NewFieldDef.DataType := FDataType;
if FSize <> 0 then
NewFieldDef.Size := FSize;
DoInitFieldDef(Col, NewFieldDef);
except
NewFieldDef.Free;
raise;
end;
end;
end;
procedure TDISqlite3UniDirQuery.InternalHandleException;
begin
{$IFDEF COMPILER_6_UP}
if Assigned(Classes.ApplicationHandleException) then
Classes.ApplicationHandleException(Self);
{$ELSE COMPILER_6_UP}
Application.HandleException(Self);
{$ENDIF COMPILER_6_UP}
end;
{$IFDEF COMPILER_6_UP}
function TDISqlite3UniDirQuery.IsSequenced: Boolean;
begin
Result := False;
end;
{$ENDIF COMPILER_6_UP}
function TDISqlite3UniDirQuery.GetCanModify: Boolean;
begin
Result := False;
end;
{$IFNDEF COMPILER_5_UP}
function TDISqlite3UniDirQuery.GetFieldClass(AFieldType: TFieldType): TFieldClass;
begin
Result := inherited GetFieldClass(AFieldType);
if not Assigned(Result) and (AFieldType = ftWideString) then
Result := TDISQLite3WideStringField;
end;
{$ENDIF !COMPILER_5_UP}
function TDISqlite3UniDirQuery.GetDatabase: TDISQLite3Database;
begin
Result := FSelectStatement.Database;
end;
function TDISqlite3UniDirQuery.GetRecord(Buffer: PAnsiChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
var
i: Integer;
begin
case GetMode of
gmNext:
case FSelectStatement.Step of
SQLITE_ROW:
begin
for i := 0 to FColumnCount - 1 do
with FRowBuffer^[i] do
begin
sqlite3_finalize_cell16(Data);
FSelectStatement.column_cell16(i, Data);
end;
Result := grOK;
Exit;
end;
SQLITE_DONE:
begin
Result := grEOF;
Exit;
end;
end;
gmCurrent:
begin
Result := grOK;
Exit;
end;
{$IFNDEF COMPILER_6_UP}
gmPrior:
begin
DatabaseError(PResStringRec(@SDataSetUnidirectional), Self);
end;
{$ENDIF !COMPILER_6_UP}
end;
Result := grError;
end;
function TDISqlite3UniDirQuery.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
var
ColumnIdx: Integer;
l: Integer;
s: AnsiString;
{$IFDEF COMPILER_10_UP}
w: WideString;
{$ENDIF COMPILER_10_UP}
begin
Result := Assigned(FRowBuffer);
if not Result then Exit;
ColumnIdx := Field.FieldNo - 1;
Result := ColumnIdx >= 0;
if not Result then Exit;
with FRowBuffer^[ColumnIdx] do
begin
Result := Data.CellType <> SQLITE_NULL;
if not Result then Exit;
if Assigned(Buffer) then
case Field.DataType of
ftBlob, ftMemo, ftGraphic, ftFmtMemo:
begin
end;
ftDate:
begin
{$IFDEF COMPILER_5_UP}
PDateTime(Buffer)^ := sqlite3_cell16_as_date(Data);
{$ELSE COMPILER_5_UP}
PInteger(Buffer)^ := DateTimeToTimeStamp(sqlite3_cell16_as_datetime(Data)).Date;
{$ENDIF COMPILER_5_UP}
end;
ftTime:
begin
{$IFDEF COMPILER_5_UP}
PDateTime(Buffer)^ := sqlite3_cell16_as_time(Data);
{$ELSE COMPILER_5_UP}
PInteger(Buffer)^ := DateTimeToTimeStamp(sqlite3_cell16_as_datetime(Data)).Time;
{$ENDIF COMPILER_5_UP}
end;
ftDateTime
{$IFDEF COMPILER_6_UP}, ftTimestamp{$ENDIF}
{$IFDEF COMPILER_10_UP}, ftOraTimeStamp{$ENDIF}:
begin
{$IFDEF COMPILER_5_UP}
PDateTime(Buffer)^ := sqlite3_cell16_as_datetime(Data);
{$ELSE COMPILER_5_UP}
PDouble(Buffer)^ := TimeStampToMSecs(DateTimeToTimeStamp(sqlite3_cell16_as_datetime(Data)));
{$ENDIF COMPILER_5_UP}
end;
ftInteger:
begin
PInteger(Buffer)^ := sqlite3_cell16_as_integer(Data);
end;
ftLargeInt:
begin
PInt64(Buffer)^ := sqlite3_cell16_as_int64(Data);
end;
ftFloat, ftCurrency:
begin
PDouble(Buffer)^ := sqlite3_cell16_as_float(Data);
end;
ftString:
begin
s := sqlite3_cell16_as_ansistring(Data);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?