📄 ibsql.pas
字号:
{************************************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ InterBase Express core components }
{ }
{ Copyright (c) 1998-2001 Borland Software Corporation }
{ }
{ InterBase Express is based in part on the product }
{ Free IB Components, written by Gregory H. Deatz for }
{ Hoagland, Longo, Moran, Dunst & Doukas Company. }
{ Free IB Components is used under license. }
{ }
{ The contents of this file are subject to the InterBase }
{ Public License Version 1.0 (the "License"); you may not }
{ use this file except in compliance with the License. You may obtain }
{ a copy of the License at http://www.borland.com/interbase/IPL.html }
{ Software distributed under the License is distributed on }
{ an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
{ express or implied. See the License for the specific language }
{ governing rights and limitations under the License. }
{ The Original Code was created by InterBase Software Corporation }
{ and its successors. }
{ Portions created by Borland Software Corporation are Copyright }
{ (C) Borland Software Corporation. All Rights Reserved. }
{ Contributor(s): Jeff Overcash }
{ }
{************************************************************************}
unit IBSQL;
interface
uses
SysUtils, Variants,
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
{$IFDEF LINUX}
Libc,
{$ENDIF}
Classes, IBHeader, IBErrorCodes, IBExternals, DB, IB, IBDatabase,
IBUtils, IBXConst;
type
TIBSQL = class;
TIBXSQLDA = class;
{ TIBXSQLVAR }
TIBXSQLVAR = class(TObject)
private
FParent: TIBXSQLDA;
FSQL: TIBSQL;
FIndex: Integer;
FModified: Boolean;
FName: String;
FXSQLVAR: PXSQLVAR; { Point to the PXSQLVAR in the owner object }
FMaxLen : Short; (** length of data area **)
function AdjustScale(Value: Int64; Scale: Integer): Double;
function AdjustScaleToInt64(Value: Int64; Scale: Integer): Int64;
function AdjustScaleToCurrency(Value: Int64; Scale: Integer): Currency;
function GetAsCurrency: Currency;
function GetAsInt64: Int64;
function GetAsDateTime: TDateTime;
function GetAsDouble: Double;
function GetAsFloat: Float;
function GetAsLong: Long;
function GetAsPointer: Pointer;
function GetAsQuad: TISC_QUAD;
function GetAsShort: Short;
function GetAsString: String;
function GetAsVariant: Variant;
function GetAsXSQLVAR: PXSQLVAR;
function GetIsNull: Boolean;
function GetIsNullable: Boolean;
function GetSize: Integer;
function GetSQLType: Integer;
procedure SetAsCurrency(Value: Currency);
procedure SetAsInt64(Value: Int64);
procedure SetAsDate(Value: TDateTime);
procedure SetAsTime(Value: TDateTime);
procedure SetAsDateTime(Value: TDateTime);
procedure SetAsDouble(Value: Double);
procedure SetAsFloat(Value: Float);
procedure SetAsLong(Value: Long);
procedure SetAsPointer(Value: Pointer);
procedure SetAsQuad(Value: TISC_QUAD);
procedure SetAsShort(Value: Short);
procedure SetAsString(Value: String);
procedure SetAsVariant(Value: Variant);
procedure SetAsXSQLVAR(Value: PXSQLVAR);
procedure SetIsNull(Value: Boolean);
procedure SetIsNullable(Value: Boolean);
procedure SetAsTrimString(const Value: String);
function GetAsTrimString: String;
public
constructor Create(Parent: TIBXSQLDA; Query: TIBSQL);
procedure Assign(Source: TIBXSQLVAR);
procedure LoadFromFile(const FileName: String);
procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(const FileName: String);
procedure SaveToStream(Stream: TStream);
procedure Clear;
property AsDate: TDateTime read GetAsDateTime write SetAsDate;
property AsTime: TDateTime read GetAsDateTime write SetAsTime;
property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
property AsDouble: Double read GetAsDouble write SetAsDouble;
property AsFloat: Float read GetAsFloat write SetAsFloat;
property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
property AsInt64: Int64 read GetAsInt64 write SetAsInt64;
property AsInteger: Integer read GetAsLong write SetAsLong;
property AsLong: Long read GetAsLong write SetAsLong;
property AsPointer: Pointer read GetAsPointer write SetAsPointer;
property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
property AsShort: Short read GetAsShort write SetAsShort;
property AsString: String read GetAsString write SetAsString;
property AsTrimString : String read GetAsTrimString write SetAsTrimString;
property AsVariant: Variant read GetAsVariant write SetAsVariant;
property AsXSQLVAR: PXSQLVAR read GetAsXSQLVAR write SetAsXSQLVAR;
property Data: PXSQLVAR read FXSQLVAR write FXSQLVAR;
property IsNull: Boolean read GetIsNull write SetIsNull;
property IsNullable: Boolean read GetIsNullable write SetIsNullable;
property Index: Integer read FIndex;
property Modified: Boolean read FModified write FModified;
property Name: String read FName;
property Size: Integer read GetSize;
property SQLType: Integer read GetSQLType;
property Value: Variant read GetAsVariant write SetAsVariant;
end;
TIBXSQLVARArray = Array of TIBXSQLVAR;
{ TIBXSQLVAR }
TIBXSQLDA = class(TObject)
protected
FSQL: TIBSQL;
FCount: Integer;
FNames: TStrings;
FSize: Integer;
FXSQLDA: PXSQLDA;
FXSQLVARs: TIBXSQLVARArray; { array of IBXQLVARs }
FUniqueRelationName: String;
function GetModified: Boolean;
function GetNames: String;
function GetRecordSize: Integer;
function GetXSQLDA: PXSQLDA;
function GetXSQLVAR(Idx: Integer): TIBXSQLVAR;
function GetXSQLVARByName(Idx: String): TIBXSQLVAR;
procedure Initialize;
procedure SetCount(Value: Integer);
public
constructor Create(Query: TIBSQL);
destructor Destroy; override;
procedure AddName(FieldName: String; Idx: Integer);
function ByName(Idx: String): TIBXSQLVAR;
property AsXSQLDA: PXSQLDA read GetXSQLDA;
property Count: Integer read FCount write SetCount;
property Modified: Boolean read GetModified;
property Names: String read GetNames;
property RecordSize: Integer read GetRecordSize;
property Vars[Idx: Integer]: TIBXSQLVAR read GetXSQLVAR; default;
property UniqueRelationName: String read FUniqueRelationName;
end;
{ TIBBatch }
TIBBatch = class(TObject)
protected
FFilename: String;
FColumns: TIBXSQLDA;
FParams: TIBXSQLDA;
public
procedure ReadyFile; virtual; abstract;
property Columns: TIBXSQLDA read FColumns write FColumns;
property Filename: String read FFilename write FFilename;
property Params: TIBXSQLDA read FParams write FParams;
end;
TIBBatchInput = class(TIBBatch)
public
function ReadParameters: Boolean; virtual; abstract;
end;
TIBBatchOutput = class(TIBBatch)
public
function WriteColumns: Boolean; virtual; abstract;
end;
{ TIBOutputDelimitedFile }
TIBOutputDelimitedFile = class(TIBBatchOutput)
protected
FFile : TFileStream;
FOutputTitles: Boolean;
FColDelimiter,
FRowDelimiter: string;
public
destructor Destroy; override;
procedure ReadyFile; override;
function WriteColumns: Boolean; override;
property ColDelimiter: string read FColDelimiter write FColDelimiter;
property OutputTitles: Boolean read FOutputTitles
write FOutputTitles;
property RowDelimiter: string read FRowDelimiter write FRowDelimiter;
end;
{ TIBInputDelimitedFile }
TIBInputDelimitedFile = class(TIBBatchInput)
protected
FColDelimiter,
FRowDelimiter: string;
FEOF: Boolean;
FFile: TFileStream;
FLookAhead: Char;
FReadBlanksAsNull: Boolean;
FSkipTitles: Boolean;
public
destructor Destroy; override;
function GetColumn(var Col: string): Integer;
function ReadParameters: Boolean; override;
procedure ReadyFile; override;
property ColDelimiter: string read FColDelimiter write FColDelimiter;
property ReadBlanksAsNull: Boolean read FReadBlanksAsNull
write FReadBlanksAsNull;
property RowDelimiter: string read FRowDelimiter write FRowDelimiter;
property SkipTitles: Boolean read FSkipTitles write FSkipTitles;
end;
{ TIBOutputRawFile }
TIBOutputRawFile = class(TIBBatchOutput)
protected
FFile : TFileStream;
public
destructor Destroy; override;
procedure ReadyFile; override;
function WriteColumns: Boolean; override;
end;
{ TIBInputRawFile }
TIBInputRawFile = class(TIBBatchInput)
protected
FFile : TFileStream;
public
destructor Destroy; override;
function ReadParameters: Boolean; override;
procedure ReadyFile; override;
end;
{ TIBSQL }
TIBSQLTypes = (SQLUnknown, SQLSelect, SQLInsert,
SQLUpdate, SQLDelete, SQLDDL,
SQLGetSegment, SQLPutSegment,
SQLExecProcedure, SQLStartTransaction,
SQLCommit, SQLRollback,
SQLSelectForUpdate, SQLSetGenerator);
TIBSQL = class(TComponent)
private
FIBLoaded: Boolean;
protected
FBase: TIBBase;
FBOF, { At BOF? }
FEOF, { At EOF? }
FGoToFirstRecordOnExecute, { Automatically position record on first record after executing }
FOpen, { Is a cursor open? }
FPrepared: Boolean; { Has the query been prepared? }
FRecordCount: Integer; { How many records have been read so far? }
FCursor: String; { Cursor name...}
FHandle: TISC_STMT_HANDLE; { Once prepared, this accesses the SQL Query }
FOnSQLChanging: TNotifyEvent; { Call this when the SQL is changing }
FSQL: TStrings; { SQL Query (by user) }
FParamCheck: Boolean; { Check for parameters? (just like TQuery) }
FProcessedSQL: TStrings; { SQL Query (pre-processed for param labels) }
FSQLParams, { Any parameters to the query }
FSQLRecord: TIBXSQLDA; { The current record }
FSQLType: TIBSQLTypes; { Select, update, delete, insert, create, alter, etc...}
FGenerateParamNames: Boolean; { Auto generate param names ?}
procedure DoBeforeDatabaseDisconnect(Sender: TObject);
function GetDatabase: TIBDatabase;
function GetDBHandle: PISC_DB_HANDLE;
function GetEOF: Boolean;
function GetFields(const Idx: Integer): TIBXSQLVAR;
function GetFieldIndex(FieldName: String): Integer;
function GetPlan: String;
function GetRecordCount: Integer;
function GetRowsAffected: Integer;
function GetSQLParams: TIBXSQLDA;
function GetTransaction: TIBTransaction;
function GetTRHandle: PISC_TR_HANDLE;
procedure PreprocessSQL;
procedure SetDatabase(Value: TIBDatabase);
procedure SetSQL(Value: TStrings);
procedure SetTransaction(Value: TIBTransaction);
procedure SQLChanging(Sender: TObject);
procedure BeforeTransactionEnd(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure BatchInput(InputObject: TIBBatchInput);
procedure BatchOutput(OutputObject: TIBBatchOutput);
function Call(ErrCode: ISC_STATUS; RaiseError: Boolean): ISC_STATUS;
procedure CheckClosed; { raise error if query is not closed. }
procedure CheckOpen; { raise error if query is not open.}
procedure CheckValidStatement; { raise error if statement is invalid.}
procedure Close;
function Current: TIBXSQLDA;
procedure ExecQuery;
function FieldByName(FieldName: String): TIBXSQLVAR;
procedure FreeHandle;
function Next: TIBXSQLDA;
procedure Prepare;
function GetUniqueRelationName: String;
function ParamByName(Idx: String): TIBXSQLVAR;
property Bof: Boolean read FBOF;
property DBHandle: PISC_DB_HANDLE read GetDBHandle;
property Eof: Boolean read GetEOF;
property Fields[const Idx: Integer]: TIBXSQLVAR read GetFields;
property FieldIndex[FieldName: String]: Integer read GetFieldIndex;
property Open: Boolean read FOpen;
property Params: TIBXSQLDA read GetSQLParams;
property Plan: String read GetPlan;
property Prepared: Boolean read FPrepared;
property RecordCount: Integer read GetRecordCount;
property RowsAffected: Integer read GetRowsAffected;
property SQLType: TIBSQLTypes read FSQLType;
property TRHandle: PISC_TR_HANDLE read GetTRHandle;
property Handle: TISC_STMT_HANDLE read FHandle;
property GenerateParamNames: Boolean read FGenerateParamNames write FGenerateParamNames;
property UniqueRelationName: String read GetUniqueRelationName;
published
property Database: TIBDatabase read GetDatabase write SetDatabase;
property GoToFirstRecordOnExecute: Boolean read FGoToFirstRecordOnExecute
write FGoToFirstRecordOnExecute
default True;
property ParamCheck: Boolean read FParamCheck write FParamCheck;
property SQL: TStrings read FSQL write SetSQL;
property Transaction: TIBTransaction read GetTransaction write SetTransaction;
property OnSQLChanging: TNotifyEvent read FOnSQLChanging write FOnSQLChanging;
end;
implementation
uses
{$IFDEF LINUX}
Types,
{$ENDIF}
IBIntf, IBBlob, IBSQLMonitor;
{ TIBXSQLVAR }
constructor TIBXSQLVAR.Create(Parent: TIBXSQLDA; Query: TIBSQL);
begin
inherited Create;
FParent := Parent;
FSQL := Query;
end;
procedure TIBXSQLVAR.Assign(Source: TIBXSQLVAR);
var
szBuff: PChar;
s_bhandle, d_bhandle: TISC_BLOB_HANDLE;
bSourceBlob, bDestBlob: Boolean;
iSegs, iMaxSeg, iSize: Long;
iBlobType: Short;
begin
szBuff := nil;
bSourceBlob := True;
bDestBlob := True;
s_bhandle := nil;
d_bhandle := nil;
try
if (Source.IsNull) then
begin
IsNull := True;
exit;
end
else
if (FXSQLVAR^.sqltype and (not 1) = SQL_ARRAY) or
(Source.FXSQLVAR^.sqltype and (not 1) = SQL_ARRAY) then
exit; { arrays not supported }
if (FXSQLVAR^.sqltype and (not 1) <> SQL_BLOB) and
(Source.FXSQLVAR^.sqltype and (not 1) <> SQL_BLOB) then
begin
AsXSQLVAR := Source.AsXSQLVAR;
exit;
end
else
if (Source.FXSQLVAR^.sqltype and (not 1) <> SQL_BLOB) then
begin
szBuff := nil;
IBAlloc(szBuff, 0, Source.FXSQLVAR^.sqllen);
Move(Source.FXSQLVAR^.sqldata[0], szBuff[0], Source.FXSQLVAR^.sqllen);
bSourceBlob := False;
iSize := Source.FXSQLVAR^.sqllen;
end
else
if (FXSQLVAR^.sqltype and (not 1) <> SQL_BLOB) then
bDestBlob := False;
if bSourceBlob then
begin
{ read the blob }
Source.FSQL.Call(isc_open_blob2(StatusVector, Source.FSQL.DBHandle,
Source.FSQL.TRHandle, @s_bhandle, PISC_QUAD(Source.FXSQLVAR.sqldata),
0, nil), True);
try
IBBlob.GetBlobInfo(@s_bhandle, iSegs, iMaxSeg, iSize,
iBlobType);
szBuff := nil;
IBAlloc(szBuff, 0, iSize);
IBBlob.ReadBlob(@s_bhandle, szBuff, iSize);
finally
Source.FSQL.Call(isc_close_blob(StatusVector, @s_bhandle), True);
end;
end;
if bDestBlob then
begin
{ write the blob }
FSQL.Call(isc_create_blob2(StatusVector, FSQL.DBHandle,
FSQL.TRHandle, @d_bhandle, PISC_QUAD(FXSQLVAR.sqldata),
0, nil), True);
try
IBBlob.WriteBlob(@d_bhandle, szBuff, iSize);
IsNull := false;
finally
FSQL.Call(isc_close_blob(StatusVector, @d_bhandle), True);
end;
end
else
begin
{ just copy the buffer }
FXSQLVAR.sqltype := SQL_TEXT;
FXSQLVAR.sqllen := iSize;
IBAlloc(FXSQLVAR.sqldata, iSize, iSize);
Move(szBuff[0], FXSQLVAR^.sqldata[0], iSize);
end;
finally
FreeMem(szBuff);
end;
end;
function TIBXSQLVAR.AdjustScale(Value: Int64; Scale: Integer): Double;
var
Scaling : Int64;
i: Integer;
Val: Double;
begin
Scaling := 1; Val := Value;
if Scale > 0 then
begin
for i := 1 to Scale do
Scaling := Scaling * 10;
result := Val * Scaling;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -