📄 zorasqlquery.pas
字号:
{********************************************************}
{ }
{ Zeos Database Objects }
{ Oracle8 Query and Table components }
{ }
{ Copyright (c) 1999-2001 Sergey Seroukhov }
{ Copyright (c) 1999-2001 Zeos Development Group }
{ }
{********************************************************}
unit ZOraSqlQuery;
interface
{$R *.dcr}
uses
SysUtils, Windows, Db, Classes, ZDirSql, ZDirOraSql, DbCommon,
ZOraSqlCon, ZOraSqlTr, ZToken, ZLibOraSql, ZSqlExtra, ZQuery,
ZSqlTypes, ZSqlItems, ZSqlBuffer;
{$INCLUDE ..\Zeos.inc}
type
TZOraSqlOption = (ooAutoIncKey);
TZOraSqlOptions = set of TZOraSqlOption;
{ Direct Oracle8 dataset with descendant of TZDataSet }
TZCustomOraSqlDataset = class(TZDataSet)
private
FExtraOptions: TZOraSqlOptions;
procedure SetDatabase(Value: TZOraSqlDatabase);
procedure SetTransact(Value: TZOraSqlTransact);
function GetDatabase: TZOraSqlDatabase;
function GetTransact: TZOraSqlTransact;
protected
{ Overriding ZDataset methods }
procedure QueryRecord; override;
procedure UpdateAfterInit(RecordData: PRecordData); override;
procedure UpdateAfterPost(OldData, NewData: PRecordData); override;
{$IFDEF WITH_IPROVIDER}
{ IProvider support }
function PSInTransaction: Boolean; override;
function PSExecuteStatement(const ASql: string; AParams: TParams;
ResultSet: Pointer): Integer; override;
procedure PSSetCommandText(const CommandText: string); override;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
procedure AddTableFields(Table: string; SqlFields: TSqlFields); override;
procedure AddTableIndices(Table: string; SqlFields: TSqlFields;
SqlIndices: TSqlIndices); override;
function FieldValueToSql(Value: string; FieldDesc: PFieldDesc): string; override;
{ Buffer support methods }
procedure CopyRecord(SqlBuffer: TSqlBuffer; Source, Dest: PRecordData); override;
procedure FreeRecord(SqlBuffer: TSqlBuffer; Value: PRecordData); override;
published
property ExtraOptions: TZOraSqlOptions read FExtraOptions write FExtraOptions;
property Database: TZOraSqlDatabase read GetDatabase write SetDatabase;
property Transaction: TZOraSqlTransact read GetTransact write SetTransact;
end;
{ Direct OraSql query with descendant of TDataSet }
TZOraSqlQuery = class(TZCustomOraSqlDataset)
public
property ParamCount;
published
property Params;
property ParamCheck;
property DataSource;
property Sql;
property RequestLive;
property Database;
property Transaction;
property Active;
end;
{ Direct OraSql query with descendant of TDataSet }
TZOraSqlTable = class(TZCustomOraSqlDataset)
published
property TableName;
property ReadOnly;
property Database;
property Transaction;
property Active;
end;
implementation
uses ZExtra, ZDBaseConst, ZBlobStream, Math;
{********** TZCustomOraSqlDataset implementation **********}
{ Class constructor }
constructor TZCustomOraSqlDataset.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Query := TDirOraSqlQuery.Create(nil, nil);
DatabaseType := dtOracle;
FExtraOptions := [];
end;
{ Set connect to database component }
procedure TZCustomOraSqlDataset.SetDatabase(Value: TZOraSqlDatabase);
begin
inherited SetDatabase(Value);
end;
{ Set connect to transact-server component }
procedure TZCustomOraSqlDataset.SetTransact(Value: TZOraSqlTransact);
begin
inherited SetTransact(Value);
end;
{ Get connect to database component }
function TZCustomOraSqlDataset.GetDatabase: TZOraSqlDatabase;
begin
Result := TZOraSqlDatabase(DatabaseObj);
end;
{ Get connect to transact-server component }
function TZCustomOraSqlDataset.GetTransact: TZOraSqlTransact;
begin
Result := TZOraSqlTransact(TransactObj);
end;
{ Read query from server to internal buffer }
procedure TZCustomOraSqlDataset.QueryRecord;
var
I, Count: Integer;
RecordData: PRecordData;
FieldDesc: PFieldDesc;
Temp: string;
TempTime: TDateTime;
TimeStamp: TTimeStamp;
BlobPtr: PRecordBlob;
Status: Integer;
Cancel: Boolean;
begin
Count := SqlBuffer.Count;
while not Query.EOF and (Count = SqlBuffer.Count) do
begin
{ Go to the record }
if SqlBuffer.FillCount > 0 then
Query.Next;
{ Invoke OnProgress event }
if Assigned(OnProgress) then
begin
Cancel := False;
OnProgress(Self, psRunning, ppFetching, Query.RecNo+1,
MaxIntValue([Query.RecNo+1, Query.RecordCount]), Cancel);
if Cancel then Query.Close;
end;
if Query.EOF then Break;
{ Getting record }
RecordData := SqlBuffer.Add;
for I := 0 to SqlBuffer.SqlFields.Count - 1 do
begin
FieldDesc := SqlBuffer.SqlFields[I];
if FieldDesc.FieldNo < 0 then Continue;
if Query.FieldIsNull(FieldDesc.FieldNo) and
not (FieldDesc.FieldType in [ftBlob, ftMemo]) then
Continue;
case FieldDesc.FieldType of
ftString:
begin
Temp := ConvertFromSqlEnc(Query.Field(FieldDesc.FieldNo));
SqlBuffer.SetFieldDataLen(FieldDesc,
PChar(Temp), RecordData, Length(Temp));
end;
ftInteger, ftFloat:
SqlBuffer.SetFieldData(FieldDesc,
Query.FieldBuffer(FieldDesc.FieldNo), RecordData);
ftDateTime:
begin
TimeStamp := DateTimeToTimeStamp(
OraDateToDateTime(Query.FieldBuffer(FieldDesc.FieldNo)));
TempTime := TimeStampToMSecs(TimeStamp);
SqlBuffer.SetFieldData(FieldDesc, @TempTime, RecordData);
end;
ftMemo, ftBlob:
begin
{ Process blob and memo fields }
BlobPtr := PRecordBlob(@RecordData.Bytes[FieldDesc.Offset+1]);
BlobPtr.Handle.Ptr := 0;
BlobPtr.Handle.PtrEx := 0;
BlobPtr.Size := 0;
BlobPtr.Data := nil;
BlobPtr.BlobType := FieldDesc.BlobType;
if not Query.FieldIsNull(FieldDesc.FieldNo) then
begin
RecordData.Bytes[FieldDesc.Offset] := 0;
{ Fill internal blobs }
if FieldDesc.BlobType = btInternal then
begin
if FieldDesc.FieldType = ftMemo then
begin
Temp := ConvertFromSqlEnc(Query.Field(FieldDesc.FieldNo));
BlobPtr.Size := Length(Temp);
BlobPtr.Data := AllocMem(BlobPtr.Size);
System.Move(PChar(Temp)^, BlobPtr.Data^, BlobPtr.Size);
end
else
begin
BlobPtr.Size := PInteger(Query.FieldBuffer(FieldDesc.FieldNo))^;
BlobPtr.Data := AllocMem(BlobPtr.Size);
System.Move((Query.FieldBuffer(FieldDesc.FieldNo)+SizeOf(Integer))^,
BlobPtr.Data^, BlobPtr.Size);
end;
end
{ Fill external blobs }
else if not Query.FieldIsNull(FieldDesc.FieldNo) then begin
Status := OCIDescriptorAlloc(TDirOraSqlConnect(Query.Connect).Handle,
POCIDescriptor(BlobPtr.Handle.Ptr), OCI_DTYPE_LOB, 0, nil);
if Status <> OCI_SUCCESS then
DatabaseError('Lob allocation error in field "' + FieldDesc.Alias + '"');
Status := OCILobAssign(TDirOraSqlConnect(Query.Connect).Handle,
TDirOraSqlTransact(Query.Transact).ErrorHandle,
PPOCIDescriptor(Query.FieldBuffer(FieldDesc.FieldNo))^,
POCIDescriptor(BlobPtr.Handle.Ptr));
if Status <> OCI_SUCCESS then
DatabaseError('Lob assign error in field "' + FieldDesc.Alias + '"');
end;
end;
end;
else
DatabaseError(SUnknownType + FieldDesc.Alias);
end;
end;
{ Filter received record }
SqlBuffer.FilterItem(SqlBuffer.Count-1);
end;
end;
{************** Sql-queries processing ******************}
{ Fill collection with fields }
procedure TZCustomOraSqlDataset.AddTableFields(Table: string;
SqlFields: TSqlFields);
var
Size: Integer;
Decimals: Integer;
FieldType: TFieldType;
Query: TDirOraSqlQuery;
Default: string;
BlobType: TBlobType;
begin
Query := TDirOraSqlQuery(Transaction.QueryHandle);
Query.ShowColumns(Table, '');
while not Query.EOF do
begin
{ Evalute field parameters }
Size := StrToIntDef(Query.Field(3), 0);
Decimals := StrToIntDef(Query.Field(6), 0);
FieldType := OraSqlToDelphiType(Query.Field(2), Size, Decimals, BlobType);
if FieldType <> ftString then Size := 0;
Default := Query.Field(5);
{ Put new field description }
SqlFields.Add(Table, Query.Field(1), '', Query.Field(2), FieldType,
Size, Decimals, atNone, Query.Field(4) = 'Y', False, Default, BlobType);
Query.Next;
end;
Query.Close;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -