1
{ $Id: interbase.pp,v 1.12 2004/05/01 23:56:59 michael Exp $
3
Copyright (c) 2000 by Pavel Stingl
6
Interbase database & dataset
8
See the file COPYING.FPC, included in this distribution,
9
for details about the copyright.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
**********************************************************************}
21
{$M+} // ### remove this!!!
25
uses SysUtils, Classes, IBase60, DB;
33
TIBTransaction = class;
35
TIBStoredProc = class;
37
EInterBaseError = class(Exception);
41
TIBDatabase = class (TDatabase)
43
FIBDatabaseHandle : pointer;
45
FStatus : array [0..19] of ISC_STATUS;
46
FTransaction : TIBTransaction;
52
procedure SetDBDialect;
53
procedure SetTransaction(Value : TIBTransaction);
55
function GetHandle : pointer; virtual;
56
{ This procedure makes connection to Interbase server internally.
57
Is visible only by descendants, in application programming
58
will be invisible. Connection you must establish by setting
59
@link(Connected) property to true, or by call of Open method.
61
procedure DoInternalConnect; override;
62
{ This procedure disconnects object from IB server internally.
63
Is visible only by descendants, in application programming
64
will be invisible. Disconnection you must make by setting
65
@link(Connected) property to false, or by call of Close method.
67
procedure DoInternalDisconnect; override;
69
procedure StartTransaction; override;
70
procedure EndTransaction; override;
71
destructor Destroy; override;
72
property Handle: Pointer read GetHandle;
74
{ On connect, TIBDatabase object retrieve SQL dialect of database file,
75
and sets this property to responding value }
76
property Dialect : integer read FDialect write FDialect;
77
{ Before firing Open method you must set @link(Password),@link(DatabaseName),
78
@link(UserName) properties in order of successfull connect to database }
79
property Password : string read FPassword write FPassword;
80
{ This property holds default transaction for database. You must assign it by hand
81
now, default assignment becomes handy, in next release, with transaction
82
handling and evidence }
83
property Transaction : TIBTransaction read FTransaction write SetTransaction;
84
{ Before firing Open method you must set @link(Password),@link(DatabaseName),
85
@link(UserName) properties in order of successfull connect to database }
86
property UserName : string read FUserName write FUserName;
87
{ The character set used in SQL statements }
88
property CharSet : string read FCharSet write FCharSet;
90
{ Identifies, if connection to Interbase server is established, or not.
91
Instead of calling Open, Close methods you can connect or disconnect
92
by setting this property to true or false.
95
{ This property holds database connect string. On local server it will be
96
absolute path to the db file, if you wanna connect over network, this
97
path looks like this: <server_name>:<path_on_server>, where server_name
98
is absolute IP address, or name of server in DNS or hosts file, path_on_server
99
is absolute path to the file again }
100
Property Role : String read FRole write FRole;
101
property DatabaseName;
102
property KeepConnection;
103
property LoginPrompt;
111
Interbase has two modes for commit and rollback transactions,
112
the difference is simple. If you execute Commit or Rollback,
113
current transaction ends, and you must create new one.
114
If you, on other side, need only commit or rollback data
115
without transaction closing, execute with CommitRetaining or
116
RollbackRetaining. Transaction handle, environment etc. will be
117
as same as before action. Possible values are : caNone, caCommit, caCommitRetaining, caRollback,
121
TCommitRollbackAction = (caNone, caCommit, caCommitRetaining, caRollback,
122
caRollbackRetaining);
123
TAccessMode = (amReadWrite, amReadOnly);
124
TIsolationLevel = (ilConcurrent, ilConsistent, ilReadCommittedRecV,
126
TLockResolution = (lrWait, lrNoWait);
127
TTableReservation = (trNone, trSharedLockRead, trSharedLockWrite,
128
trProtectedLockRead, trProtectedLockWrite);
130
TIBTransaction = class (TComponent)
132
FTransactionHandle : pointer; // Transaction handle
133
FAction : TCommitRollbackAction;
135
FTPB : string; // Transaction parameter buffer
136
FDatabase : TIBDatabase;
137
FAccessMode : TAccessMode;
138
FIsolationLevel : TIsolationLevel;
139
FLockResolution : TLockResolution;
140
FTableReservation : TTableReservation;
141
FStatus : array [0..19] of ISC_STATUS;
143
procedure SetActive(Value : boolean);
146
function GetHandle : pointer; virtual;
148
{ Commits all actions, which was made in transaction, and closes transaction}
149
procedure Commit; virtual;
150
{ Commits all actions, closes transaction, and creates new one }
151
procedure CommitRetaining; virtual;
152
{ Rollbacks all actions made in transaction, and closes transaction }
153
procedure Rollback; virtual;
154
{ Rollbacks all actions made in transaction, closes trans. and creates new one }
155
procedure RollbackRetaining; virtual;
156
{ Creates new transaction. If transaction is active, closes it and make new one.
157
Action taken while closing responds to @link(Action) property settings }
158
procedure StartTransaction;
159
constructor Create(AOwner : TComponent); override;
160
destructor Destroy; override;
161
property Handle: Pointer read GetHandle;
163
{ Default action while closing transaction by setting
164
@link(Active) property. For details see @link(TCommitRollbackAction)}
165
property Action : TCommitRollbackAction read FAction write FAction;
166
{ Is set to true while transaction is active, false if not.
167
If you set it manually to true, object executes
168
@link(StartTransaction) method, if transaction is
169
active, and you set Active to false, object executes
170
one of @link(Commit), @link(CommitRetaining), @link(Rollback),
171
@link(RollbackRetaining) methods, depending on @link(Action) property
174
property Active : boolean read FActive write SetActive;
175
{ Transaction must be assigned to some database session, for which purpose
176
you must use this property}
177
property Database : TIBDatabase read FDatabase write FDatabase;
182
PIBBookmark = ^TIBBookmark;
184
BookmarkData : integer;
185
BookmarkFlag : TBookmarkFlag;
188
TStatementType = (stNone, stSelect, stInsert, stUpdate, stDelete,
189
stDDL, stGetSegment, stPutSegment, stExecProcedure,
190
stStartTrans, stCommit, stRollback, stSelectForUpd);
192
TIBQuery = class (TDBDataset)
195
FTransaction : TIBTransaction;
196
FDatabase : TIBDatabase;
197
FStatus : array [0..19] of ISC_STATUS;
198
FFieldFlag : array [0..1023] of shortint;
199
FBufferSize : integer;
201
FSQLDAAllocated : integer;
202
FStatement : pointer;
203
FRecordCount : integer;
205
FCurrentRecord : integer;
209
FStatementType : TStatementType;
210
FLoadingFieldDefs : boolean;
212
procedure SetDatabase(Value : TIBDatabase);
213
procedure SetTransaction(Value : TIBTransaction);
214
procedure AllocSQLDA(Count : integer);
215
procedure AllocStatement;
216
procedure FreeStatement;
217
procedure PrepareStatement;
218
procedure DescribeStatement;
219
procedure SetUpSQLVars;
220
procedure AllocFldBuffers;
221
procedure FreeFldBuffers;
223
function LoadBufferFromSQLDA(Buffer : PChar): TGetResult;
224
procedure GetStatementType;
225
procedure SetFieldSizes;
226
procedure TranslateFldType(SQLType, SQLLen : integer; var LensSet : boolean;
227
var TrType : TFieldType; var TrLen : word);
229
procedure ExecuteImmediate;
230
procedure ExecuteParams;
233
// conversion methods
234
procedure GetDateTime(CurrBuff, Buffer : pointer; AType : integer);
235
procedure GetFloat(CurrBuff, Buffer : pointer; Field : TField);
239
// abstract & virual methods of TDataset
240
function AllocRecordBuffer: PChar; override;
241
procedure FreeRecordBuffer(var Buffer: PChar); override;
242
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
243
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
244
function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
245
function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
246
function GetRecordCount: integer; override;
247
function GetRecordSize: Word; override;
248
procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
249
procedure InternalClose; override;
250
procedure InternalDelete; override;
251
procedure InternalFirst; override;
252
procedure InternalGotoBookmark(ABookmark: Pointer); override;
253
procedure InternalHandleException; override;
254
procedure InternalInitFieldDefs; override;
255
procedure InternalInitRecord(Buffer: PChar); override;
256
procedure InternalLast; override;
257
procedure InternalOpen; override;
258
procedure InternalPost; override;
259
procedure InternalSetToRecord(Buffer: PChar); override;
260
function IsCursorOpen: Boolean; override;
261
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
262
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
263
procedure SetFieldData(Field: TField; Buffer: Pointer); override;
265
{ This method is used for executing sql statements, which
266
doesn't return any rows. (insert,delete,update, and DDL commands) }
267
procedure ExecSQL; virtual;
268
constructor Create(AOwner : TComponent); override;
269
destructor Destroy; override;
271
{ Query must have transaction assigned. If transaction is not assigned, and database
272
is, object looks, if database have default transaction, and assigns it }
273
property Transaction : TIBTransaction read FTransaction write SetTransaction;
274
{ Use this property to determine, which database session can query use }
275
property Database : TIBDatabase read FDatabase write SetDatabase;
276
{ This property holds SQL command, which you want to execute }
277
property SQL : TStrings read FSQL write FSQL;
278
// Publish TDataset properties.
280
property AutoCalcFields;
283
property BeforeClose;
285
property BeforeInsert;
286
property AfterInsert;
291
property BeforeCancel;
292
property AfterCancel;
293
property BeforeDelete;
294
property AfterDelete;
295
property BeforeScroll;
296
property AfterScroll;
297
property OnCalcFields;
298
property OnDeleteError;
299
property OnEditError;
300
property OnFilterRecord;
301
property OnNewRecord;
302
property OnPostError;
305
{ TIBStoredProc - not implemented - yet :-/}
307
TIBStoredProc = class (TDataset)
328
__tm_gmtoff : longint;
332
procedure CheckError(ProcName : string; Status : array of ISC_STATUS);
334
buf : array [0..1024] of char;
338
if ((Status[0] = 1) and (Status[1] <> 0)) then
341
while isc_interprete(Buf, @p) > 0 do
342
Msg := Msg + #10' -' + StrPas(Buf);
343
raise EInterBaseError.Create(ProcName + ': ' + Msg);
349
procedure TIBDatabase.SetDBDialect;
354
ResBuf : array [0..39] of byte;
356
Buffer := Chr(isc_info_db_sql_dialect) + Chr(isc_info_end);
357
if isc_database_info(@FStatus, @FIBDatabaseHandle, Length(Buffer),
358
@Buffer[1], SizeOf(ResBuf), @ResBuf) <> 0 then
359
CheckError('TIBDatabse.SetDBDialect', FStatus);
363
isc_info_db_sql_dialect :
366
Len := isc_vax_integer(@ResBuf[x], 2);
368
FDialect := isc_vax_integer(@ResBuf[x], Len);
371
isc_info_end : Break;
375
procedure TIBDatabase.SetTransaction(Value : TIBTransaction);
377
if FTransaction = nil then
379
FTransaction := Value;
380
if Assigned(FTransaction) then
381
FTransaction.Database := Self;
385
if (Value <> FTransaction) and (Value <> nil) then
386
if (not FTransaction.Active) then
388
FTransaction := Value;
389
FTransaction.Database := Self;
392
raise EInterBaseError.Create('Cannot assign transaction while old transaction active!');
395
function TIBDatabase.GetHandle: pointer;
397
Result := FIBDatabaseHandle;
400
procedure TIBDatabase.DoInternalConnect;
406
DPB := chr(isc_dpb_version1);
407
if (FUserName <> '') then
409
DPB := DPB + chr(isc_dpb_user_name) + chr(Length(FUserName)) + FUserName;
410
if (FPassword <> '') then
411
DPB := DPB + chr(isc_dpb_password) + chr(Length(FPassword)) + FPassword;
413
if (FRole <> '') then
414
DPB := DPB + chr(isc_dpb_sql_role_name) + chr(Length(FRole)) + FRole;
415
if Length(CharSet) > 0 then
416
DPB := DPB + Chr(isc_dpb_lc_ctype) + Chr(Length(CharSet)) + CharSet;
418
if (DatabaseName = '') then
419
raise EInterBaseError.Create('TIBDatabase.Open: Database connect string not filled in!');
420
FIBDatabaseHandle := nil;
421
if isc_attach_database(@FStatus, Length(DatabaseName), @DatabaseName[1], @FIBDatabaseHandle,
422
Length(DPB), @DPB[1]) <> 0 then
423
CheckError('TIBDatabase.Open', FStatus);
427
procedure TIBDatabase.DoInternalDisconnect;
429
if not Connected then
431
FIBDatabaseHandle := nil;
434
isc_detach_database(@FStatus[0], @FIBDatabaseHandle);
435
CheckError('TIBDatabase.Close', FStatus);
438
procedure TIBDatabase.StartTransaction;
440
if FTransaction = nil then
441
raise EDatabaseError.Create('TIBDatabase.StartTransaction: Transaction not set');
442
FTransaction.Active := True;
445
procedure TIBDatabase.EndTransaction;
447
if FTransaction = nil then
448
raise EDatabaseError.Create('TIBDatabase.EndTransaction: Transaction not set');
449
FTransaction.Active := False;
452
destructor TIBDatabase.Destroy;
454
if FTransaction <> nil then
456
FTransaction.Active := False;
457
FTransaction.Database := nil;
464
procedure TIBTransaction.SetActive(Value : boolean);
466
if FActive and (not Value) then
468
else if (not FActive) and Value then
472
procedure TIBTransaction.SetTPB;
474
FTPB := chr(isc_tpb_version3);
477
amReadWrite : FTPB := FTPB + chr(isc_tpb_write);
478
amReadOnly : FTPB := FTPB + chr(isc_tpb_read);
481
case FIsolationLevel of
482
ilConsistent : FTPB := FTPB + chr(isc_tpb_consistency);
483
ilConcurrent : FTPB := FTPB + chr(isc_tpb_concurrency);
484
ilReadCommittedRecV : FTPB := FTPB + chr(isc_tpb_read_committed) +
485
chr(isc_tpb_rec_version);
486
ilReadCommitted : FTPB := FTPB + chr(isc_tpb_read_committed) +
487
chr(isc_tpb_no_rec_version);
490
case FLockResolution of
491
lrWait : FTPB := FTPB + chr(isc_tpb_wait);
492
lrNoWait : FTPB := FTPB + chr(isc_tpb_nowait);
495
case FTableReservation of
496
trSharedLockRead : FTPB := FTPB + chr(isc_tpb_shared) +
497
chr(isc_tpb_lock_read);
498
trSharedLockWrite : FTPB := FTPB + chr(isc_tpb_shared) +
499
chr(isc_tpb_lock_write);
500
trProtectedLockRead : FTPB := FTPB + chr(isc_tpb_protected) +
501
chr(isc_tpb_lock_read);
502
trProtectedLockWrite : FTPB := FTPB + chr(isc_tpb_protected) +
503
chr(isc_tpb_lock_write);
507
function TIBTransaction.GetHandle: pointer;
509
Result := FTransactionHandle;
512
procedure TIBTransaction.Commit;
514
if not FActive then Exit;
515
if isc_commit_transaction(@FStatus, @FTransactionHandle) <> 0 then
516
CheckError('TIBTransaction.Commit', FStatus)
517
else FActive := False;
520
procedure TIBTransaction.CommitRetaining;
522
if not FActive then Exit;
523
if isc_commit_retaining(@FStatus, @FTransactionHandle) <> 0 then
524
CheckError('TIBTransaction.CommitRetaining', FStatus);
527
procedure TIBTransaction.Rollback;
529
if not FActive then Exit;
530
if isc_rollback_transaction(@FStatus, @FTransactionHandle) <> 0 then
531
CheckError('TIBTransaction.Rollback', FStatus)
532
else FActive := False;
535
procedure TIBTransaction.RollbackRetaining;
537
if not FActive then Exit;
538
if isc_rollback_retaining(@FStatus, @FTransactionHandle) <> 0 then
539
CheckError('TIBTransaction.RollbackRetaining', FStatus);
542
procedure TIBTransaction.StartTransaction;
546
if Active then Active := False;
548
if FDatabase = nil then
549
raise EInterBaseError.Create('TIBTransaction.StartTransaction: Database not assigned!');
551
if not Database.Connected then
554
DBHandle := Database.GetHandle;
556
FTransactionHandle := nil;
558
if isc_start_transaction(@FStatus, @FTransactionHandle, 1,
559
[@DBHandle, Length(FTPB), @FTPB[1]]) <> 0 then
560
CheckError('TIBTransaction.StartTransaction',FStatus)
561
else FActive := True;
564
constructor TIBTransaction.Create(AOwner : TComponent);
566
inherited Create(AOwner);
567
FIsolationLevel := ilReadCommitted;
570
destructor TIBTransaction.Destroy;
572
// This will also do a Rollback, if the transaction is currently active
575
if Database <> nil then
576
Database.Transaction := nil;
582
procedure TIBQuery.SetTransaction(Value : TIBTransaction);
585
if (FTransaction <> Value) then
586
FTransaction := Value;
589
procedure TIBQuery.SetDatabase(Value : TIBDatabase);
592
if (FDatabase <> Value) then
595
if (FTransaction = nil) and (Assigned(FDatabase.Transaction)) then
596
SetTransaction(FDatabase.Transaction);
600
procedure TIBQuery.AllocSQLDA(Count : integer);
602
if FSQLDAAllocated > 0 then
604
GetMem(FSQLDA, XSQLDA_Length(Count));
605
{ Zero out the memory block to avoid problems with exceptions within the
606
constructor of this class. }
607
FillChar(FSQLDA^, XSQLDA_Length(Count), 0);
608
FSQLDAAllocated := Count;
609
FSQLDA^.Version := sqlda_version1;
610
FSQLDA^.SQLN := Count;
613
procedure TIBQuery.AllocStatement;
617
if not FDatabase.Connected then
619
dh := FDatabase.GetHandle;
621
if isc_dsql_allocate_statement(@FStatus, @dh, @FStatement) <> 0 then
622
CheckError('TIBQuery.AllocStatement', FStatus);
625
procedure TIBQuery.FreeStatement;
627
if isc_dsql_free_statement(@FStatus, @FStatement, DSQL_Drop) <> 0 then
628
CheckError('TIBQuery.FreeStatement', FStatus);
632
procedure TIBQuery.PrepareStatement;
638
tr := FTransaction.GetHandle;
640
for x := 0 to FSQL.Count - 1 do
641
Buf := Buf + FSQL[x] + ' ';
643
if isc_dsql_prepare(@FStatus, @tr, @FStatement, 0, @Buf[1], Database.Dialect, nil) <> 0 then
644
CheckError('TIBQuery.PrepareStatement', FStatus);
647
procedure TIBQuery.DescribeStatement;
649
if isc_dsql_describe(@FStatus, @FStatement, 1, FSQLDA) <> 0 then
650
CheckError('TIBQuery.DescribeStatement', FStatus);
651
if FSQLDA^.SQLD > FSQLDA^.SQLN then
653
AllocSQLDA(FSQLDA^.SQLD);
654
if isc_dsql_describe(@FStatus, @FStatement, 1, FSQLDA) <> 0 then
655
CheckError('TIBQuery.DescribeStatement', FStatus);
659
procedure TIBQuery.SetUpSQLVars;
663
for x := 0 to FSQLDA^.SQLN - 1 do
665
case FSQLDA^.SQLVar[x].SQLType of
667
FSQLDA^.SQLVar[x].SQLType := sql_varying;
669
FSQLDA^.SQLVar[x].SQLType := sql_text;
670
sql_short, sql_short + 1, sql_long + 1:
671
FSQLDA^.SQLVar[x].SQLType := sql_long;
673
FSQLDA^.SQLVar[x].SQLType := sql_float;
675
FSQLDA^.SQLVar[x].SQLType := sql_double;
677
FSQLDA^.SQLVar[x].SQLType := sql_blob;
679
FSQLDA^.SQLVar[x].SQLType := sql_type_time;
681
FSQLDA^.SQLVar[x].SQLType := sql_timestamp;
686
procedure TIBQuery.AllocFldBuffers;
691
for x := 0 to FSQLDA^.SQLD - 1 do
693
FSQLDA^.SQLVar[x].SQLData := AllocMem(FSQLDA^.SQLVar[x].SQLLen);
694
FSQLDA^.SQLVar[x].SQLInd := @FFieldFlag[x];
699
procedure TIBQuery.FreeFldBuffers;
704
for x := 0 to FSQLDA^.SQLD - 1 do
706
if FSQLDA^.SQLVar[x].SQLData <> nil then
708
FreeMem(FSQLDA^.SQLVar[x].SQLData);
709
FSQLDA^.SQLVar[x].SQLData := nil;
715
procedure TIBQuery.Fetch;
719
if not (FStatementType in [stSelect]) then
722
retcode := isc_dsql_fetch(@FStatus, @FStatement, 1, FSQLDA);
723
if (retcode <> 0) and (retcode <> 100) then
724
CheckError('TIBQuery.Fetch', FStatus);
726
FIsEOF := (retcode = 100);
729
function TIBQuery.LoadBufferFromSQLDA(Buffer : PChar): TGetResult;
743
for x := 0 to FSQLDA^.SQLD - 1 do
745
with FSQLDA^.SQLVar[x] do
747
if ((SQLType and not 1) = SQL_VARYING) then
749
Move(SQLData^, VarcharLen, 2);
750
Move((SQLData + 2)^, Buffer^, VarcharLen);
751
PChar(Buffer + VarcharLen)^ := #0;
753
else Move(SQLData^, Buffer^, SQLLen);
762
procedure TIBQuery.GetStatementType;
765
ResBuf : array [0..7] of char;
767
FStatementType := stNone;
768
x := isc_info_sql_stmt_type;
769
if isc_dsql_sql_info(@FStatus, @FStatement, SizeOf(X),
770
@x, SizeOf(ResBuf), @ResBuf) <> 0 then
771
CheckError('TIBQuery.GetStatementType', FStatus);
772
if Ord(ResBuf[0]) = isc_info_sql_stmt_type then
774
x := isc_vax_integer(@ResBuf[1], 2);
775
FStatementType := TStatementType(isc_vax_integer(@ResBuf[3], x));
779
procedure TIBQuery.SetFieldSizes;
786
for x := 0 to FSQLDA^.SQLD - 1 do
787
Inc(FRecordSize, FSQLDA^.SQLVar[x].SQLLen);
789
FBufferSize := FRecordSize + SizeOf(TIBBookmark);
792
procedure TIBQuery.TranslateFldType(SQLType, SQLLen : integer; var LensSet : boolean;
793
var TrType : TFieldType; var TrLen : word);
797
case (SQLType and not 1) of
811
TrType := ftDateTime;
813
TrType := ftDateTime;
815
TrType := ftDateTime;
851
procedure TIBQuery.ExecuteImmediate;
855
procedure TIBQuery.ExecuteParams;
857
//!! to be implemented
860
procedure TIBQuery.Execute;
864
tr := FTransaction.GetHandle;
865
if isc_dsql_execute(@FStatus, @tr, @FStatement, 1, nil) <> 0 then
866
CheckError('TIBQuery.Execute', FStatus);
869
procedure TIBQuery.GetDateTime(CurrBuff, Buffer : pointer; AType : integer);
871
CTime : TTm; // C struct time
872
STime : TSystemTime; // System time
873
PTime : TDateTime; // Pascal time
875
case (AType and not 1) of
877
isc_decode_sql_date(PISC_DATE(CurrBuff), @CTime);
879
isc_decode_sql_time(PISC_TIME(CurrBuff), @CTime);
881
isc_decode_timestamp(PISC_TIMESTAMP(CurrBuff), @CTime);
883
STime.Year := CTime.tm_year + 1900;
884
STime.Month := CTime.tm_mon + 1;
885
STime.Day := CTime.tm_mday;
886
STime.Hour := CTime.tm_hour;
887
STime.Minute := CTime.tm_min;
888
STime.Second := CTime.tm_sec;
889
STime.Millisecond := 0;
891
PTime := SystemTimeToDateTime(STime);
892
Move(PTime, Buffer^, SizeOf(PTime));
895
procedure TIBQuery.GetFloat(CurrBuff, Buffer : pointer; Field : TField);
904
Move(CurrBuff^, Sin, 4);
909
Move(CurrBuff^, Dbl, 8);
912
10: Move(CurrBuff^, Ext, 10);
914
Move(Ext, Buffer^, 10);
917
function TIBQuery.AllocRecordBuffer: PChar;
919
Result := AllocMem(FBufferSize);
922
procedure TIBQuery.FreeRecordBuffer(var Buffer: PChar);
924
if Assigned(@Buffer) then
928
procedure TIBQuery.GetBookmarkData(Buffer: PChar; Data: Pointer);
930
PInteger(Data)^ := PIBBookmark(Buffer + FRecordSize)^.BookmarkData;
933
function TIBQuery.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
935
Result := PIBBookmark(Buffer + FRecordSize)^.BookmarkFlag;
938
function TIBQuery.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
945
CurrBuff := ActiveBuffer;
947
for x := 0 to FSQLDA^.SQLD - 1 do
950
if (Field.FieldName = FSQLDA^.SQLVar[x].SQLName) then
952
case Field.DataType of
957
Move(CurrBuff^, Buffer^, Field.Size);
959
ftDate, ftTime, ftDateTime:
960
GetDateTime(CurrBuff, Buffer, FSQLDA^.SQLVar[x].SQLType);
963
Move(CurrBuff^, Buffer^, Field.Size);
964
PChar(Buffer + Field.Size)^ := #0;
967
GetFloat(CurrBuff, Buffer, Field);
974
else Inc(CurrBuff, FSQLDA^.SQLVar[x].SQLLen);
979
function TIBQuery.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
981
if FStatementType <> stSelect then
992
if FCurrentRecord <= 0 then
995
FCurrentRecord := -1;
997
else Dec(FCurrentRecord);
999
if (FCurrentRecord < 0) or (FCurrentRecord >= RecordCount) then
1002
if FCurrentRecord >= (RecordCount - 1) then
1004
Result := LoadBufferFromSQLDA(Buffer);
1005
if Result = grOK then
1007
Inc(FCurrentRecord);
1011
else Inc(FCurrentRecord);
1015
if Result = grOK then
1017
with PIBBookmark(Buffer + FRecordSize)^ do
1019
BookmarkData := FCurrentRecord;
1020
BookmarkFlag := bfCurrent;
1023
else if (Result = grError) then
1024
DatabaseError('No record');
1027
function TIBQuery.GetRecordCount: integer;
1029
Result := FRecordCount;
1032
function TIBQuery.GetRecordSize: Word;
1034
Result := FRecordSize;
1037
procedure TIBQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
1039
// not implemented - sql dataset
1042
procedure TIBQuery.InternalClose;
1046
if DefaultFields then
1049
FCurrentRecord := -1;
1056
procedure TIBQuery.InternalDelete;
1058
// not implemented - sql dataset
1061
procedure TIBQuery.InternalFirst;
1063
FCurrentRecord := -1;
1066
procedure TIBQuery.InternalGotoBookmark(ABookmark: Pointer);
1068
FCurrentRecord := PInteger(ABookmark)^;
1071
procedure TIBQuery.InternalHandleException;
1075
procedure TIBQuery.InternalInitFieldDefs;
1080
TransType : TFieldType;
1082
if FLoadingFieldDefs then
1085
FLoadingFieldDefs := True;
1090
for x := 0 to FSQLDA^.SQLD - 1 do
1092
TranslateFldType(FSQLDA^.SQLVar[x].SQLType, FSQLDA^.SQLVar[x].SQLLen, lenset,
1093
TransType, TransLen);
1094
TFieldDef.Create(FieldDefs, FSQLDA^.SQLVar[x].SQLName, TransType,
1095
TransLen, False, (x + 1));
1099
FLoadingFieldDefs := False;
1103
procedure TIBQuery.InternalInitRecord(Buffer: PChar);
1105
FillChar(Buffer^, FBufferSize, #0);
1108
procedure TIBQuery.InternalLast;
1110
FCurrentRecord := RecordCount;
1113
procedure TIBQuery.InternalOpen;
1119
if FStatementType in [stSelect] then
1125
InternalInitFieldDefs;
1126
if DefaultFields then
1138
procedure TIBQuery.InternalPost;
1140
// not implemented - sql dataset
1143
procedure TIBQuery.InternalSetToRecord(Buffer: PChar);
1145
FCurrentRecord := PIBBookmark(Buffer + FRecordSize)^.BookmarkData;
1148
function TIBQuery.IsCursorOpen: Boolean;
1153
procedure TIBQuery.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
1155
PIBBookmark(Buffer + FRecordSize)^.BookmarkFlag := Value;
1158
procedure TIBQuery.SetBookmarkData(Buffer: PChar; Data: Pointer);
1160
PIBBookmark(Buffer + FRecordSize)^.BookmarkData := PInteger(Data)^;
1163
procedure TIBQuery.SetFieldData(Field: TField; Buffer: Pointer);
1169
procedure TIBQuery.ExecSQL;
1181
constructor TIBQuery.Create(AOwner : TComponent);
1183
inherited Create(AOwner);
1184
FSQL := TStringList.Create;
1185
FCurrentRecord := -1;
1189
destructor TIBQuery.Destroy;
1191
if Active then Close;
1202
$Log: interbase.pp,v $
1203
Revision 1.12 2004/05/01 23:56:59 michael
1204
+ Published TDataset properties
1206
Revision 1.11 2003/12/07 23:13:34 sg
1207
* Added Log entries to end of file