1 {*********************************************************}
3 { Zeos Database Objects }
4 { Caching Classes and Interfaces }
6 { Originally written by Sergey Seroukhov }
8 {*********************************************************}
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
13 { License Agreement: }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
46 { http://www.sourceforge.net/projects/zeoslib. }
49 { Zeos Development Group. }
50 {********************************************************@}
52 unit ZDbcCachedResultSet;
59 Types, Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils, Contnrs,
60 ZClasses, ZDbcIntfs, ZDbcResultSet, ZDbcCache, ZCompatibility;
63 // Forward declarations.
64 IZCachedResultSet = interface;
66 {** Resolver to post updates. }
67 IZCachedResolver = interface (IZInterface)
68 ['{546ED716-BB88-468C-8CCE-D7111CF5E1EF}']
70 procedure CalculateDefaults(Sender: IZCachedResultSet;
71 RowAccessor: TZRowAccessor);
72 procedure PostUpdates(Sender: IZCachedResultSet; UpdateType: TZRowUpdateType;
73 OldRowAccessor, NewRowAccessor: TZRowAccessor);
74 {BEGIN of PATCH [1185969]: Do tasks after posting updates. ie: Updating AutoInc fields in MySQL }
75 procedure UpdateAutoIncrementFields(Sender: IZCachedResultSet; UpdateType: TZRowUpdateType;
76 OldRowAccessor, NewRowAccessor: TZRowAccessor; Resolver: IZCachedResolver);
77 {END of PATCH [1185969]: Do tasks after posting updates. ie: Updating AutoInc fields in MySQL }
78 procedure RefreshCurrentRow(Sender: IZCachedResultSet;RowAccessor: TZRowAccessor); //FOS+ 07112006
81 {** Represents a cached result set. }
82 IZCachedResultSet = interface (IZResultSet)
83 ['{BAF24A92-C8CE-4AB4-AEBC-3D4A9BCB0946}']
85 function GetResolver: IZCachedResolver;
86 procedure SetResolver(Resolver: IZCachedResolver);
88 {BEGIN PATCH [1214009] Calc Defaults in TZUpdateSQL and Added Methods to GET and SET the database Native Resolver
89 will help to implemented feature to Calculate default values in TZUpdateSQL
90 comment: add this properties to get the original Resolver
91 this will be useful whn using TZUpdateSQL //added by fduenas
93 function GetNativeResolver: IZCachedResolver;
94 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
96 function IsCachedUpdates: Boolean;
97 procedure SetCachedUpdates(Value: Boolean);
98 function IsPendingUpdates: Boolean;
100 procedure PostUpdates;
101 procedure CancelUpdates;
102 procedure PostUpdatesCached;
103 procedure DisposeCachedUpdates;
104 procedure RevertRecord;
105 procedure MoveToInitialRow;
106 procedure RefreshRow; // FOS+ 071106
109 {** Implements cached ResultSet. }
110 TZAbstractCachedResultSet = class (TZAbstractResultSet, IZCachedResultSet)
112 FCachedUpdates: Boolean;
114 FInitialRowsList: TList;
115 FCurrentRowsList: TList;
116 FSelectedRow: PZRowBuffer;
117 FUpdatedRow: PZRowBuffer;
118 FInsertedRow: PZRowBuffer;
119 FRowAccessor: TZRowAccessor;
120 FNewRowAccessor: TZRowAccessor;
121 FOldRowAccessor: TZRowAccessor;
122 FNextRowIndex: Integer;
123 FResolver: IZCachedResolver;
124 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
125 FNativeResolver: IZCachedResolver;
126 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
128 procedure CheckAvailable;
129 procedure CheckUpdatable;
130 procedure Open; override;
131 function GetNextRowIndex: Integer;
133 procedure CalculateRowDefaults(RowAccessor: TZRowAccessor); virtual;
134 procedure PostRowUpdates(OldRowAccessor,
135 NewRowAccessor: TZRowAccessor); virtual;
136 function LocateRow(RowsList: TList; RowIndex: Integer): Integer;
137 function AppendRow(Row: PZRowBuffer): PZRowBuffer;
138 procedure PrepareRowForUpdates;
140 property CachedUpdates: Boolean read FCachedUpdates write FCachedUpdates;
141 property RowsList: TList read FRowsList write FRowsList;
142 property InitialRowsList: TList read FInitialRowsList
143 write FInitialRowsList;
144 property CurrentRowsList: TList read FCurrentRowsList
145 write FCurrentRowsList;
146 property SelectedRow: PZRowBuffer read FSelectedRow write FSelectedRow;
147 property UpdatedRow: PZRowBuffer read FUpdatedRow write FUpdatedRow;
148 property InsertedRow: PZRowBuffer read FInsertedRow write FInsertedRow;
149 property RowAccessor: TZRowAccessor read FRowAccessor write FRowAccessor;
150 property OldRowAccessor: TZRowAccessor read FOldRowAccessor
151 write FOldRowAccessor;
152 property NewRowAccessor: TZRowAccessor read FNewRowAccessor
153 write FNewRowAccessor;
154 property NextRowIndex: Integer read FNextRowIndex write FNextRowIndex;
155 property Resolver: IZCachedResolver read FResolver write FResolver;
156 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
157 property NativeResolver: IZCachedResolver read FNativeResolver;
158 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
160 constructor CreateWithStatement(SQL: string; Statement: IZStatement;
161 ConSettings: PZConSettings);
162 constructor CreateWithColumns(ColumnsInfo: TObjectList; SQL: string;
163 ConSettings: PZConSettings);
164 destructor Destroy; override;
166 procedure Close; override;
168 //======================================================================
169 // Methods for accessing results by column index
170 //======================================================================
172 function IsNull(ColumnIndex: Integer): Boolean; override;
173 function GetPChar(ColumnIndex: Integer): PChar; override;
174 function GetString(ColumnIndex: Integer): String; override;
175 function GetUnicodeString(ColumnIndex: Integer): Widestring; override;
176 function GetBoolean(ColumnIndex: Integer): Boolean; override;
177 function GetByte(ColumnIndex: Integer): Byte; override;
178 function GetShort(ColumnIndex: Integer): SmallInt; override;
179 function GetInt(ColumnIndex: Integer): Integer; override;
180 function GetLong(ColumnIndex: Integer): Int64; override;
181 function GetFloat(ColumnIndex: Integer): Single; override;
182 function GetDouble(ColumnIndex: Integer): Double; override;
183 function GetBigDecimal(ColumnIndex: Integer): Extended; override;
184 function GetBytes(ColumnIndex: Integer): TByteDynArray; override;
185 function GetDate(ColumnIndex: Integer): TDateTime; override;
186 function GetTime(ColumnIndex: Integer): TDateTime; override;
187 function GetTimestamp(ColumnIndex: Integer): TDateTime; override;
188 function GetBlob(ColumnIndex: Integer): IZBlob; override;
189 function GetDefaultExpression(ColumnIndex: Integer): string; override;
191 //---------------------------------------------------------------------
192 // Traversal/Positioning
193 //---------------------------------------------------------------------
195 function MoveAbsolute(Row: Integer): Boolean; override;
197 //---------------------------------------------------------------------
199 //---------------------------------------------------------------------
201 function RowUpdated: Boolean; override;
202 function RowInserted: Boolean; override;
203 function RowDeleted: Boolean; override;
205 procedure UpdateNull(ColumnIndex: Integer); override;
206 procedure UpdateBoolean(ColumnIndex: Integer; Value: Boolean); override;
207 procedure UpdateByte(ColumnIndex: Integer; Value: ShortInt); override;
208 procedure UpdateShort(ColumnIndex: Integer; Value: SmallInt); override;
209 procedure UpdateInt(ColumnIndex: Integer; Value: Integer); override;
210 procedure UpdateLong(ColumnIndex: Integer; Value: Int64); override;
211 procedure UpdateFloat(ColumnIndex: Integer; Value: Single); override;
212 procedure UpdateDouble(ColumnIndex: Integer; Value: Double); override;
213 procedure UpdateBigDecimal(ColumnIndex: Integer; Value: Extended); override;
214 procedure UpdatePChar(ColumnIndex: Integer; Value: PChar); override;
215 procedure UpdateString(ColumnIndex: Integer; const Value: String); override;
216 procedure UpdateUnicodeString(ColumnIndex: Integer; const Value: WideString); override;
217 procedure UpdateBytes(ColumnIndex: Integer; const Value: TByteDynArray); override;
218 procedure UpdateDate(ColumnIndex: Integer; Value: TDateTime); override;
219 procedure UpdateTime(ColumnIndex: Integer; Value: TDateTime); override;
220 procedure UpdateTimestamp(ColumnIndex: Integer; Value: TDateTime); override;
221 procedure UpdateAsciiStream(ColumnIndex: Integer; Value: TStream); override;
222 procedure UpdateUnicodeStream(ColumnIndex: Integer; Value: TStream); override;
223 procedure UpdateBinaryStream(ColumnIndex: Integer; Value: TStream); override;
224 procedure UpdateDefaultExpression(ColumnIndex: Integer; const Value: string); override;
226 procedure InsertRow; override;
227 procedure UpdateRow; override;
228 procedure DeleteRow; override;
229 procedure CancelRowUpdates; override;
230 procedure RefreshRow;override;// FOS+ 071106
233 procedure MoveToInsertRow; override;
234 procedure MoveToCurrentRow; override;
236 function CompareRows(Row1, Row2: Integer; const ColumnIndices: TIntegerDynArray;
237 const ColumnDirs: TBooleanDynArray): Integer; override;
239 //---------------------------------------------------------------------
241 //---------------------------------------------------------------------
243 function GetResolver: IZCachedResolver;
244 procedure SetResolver(Resolver: IZCachedResolver);
245 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
246 function GetNativeResolver: IZCachedResolver;
247 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
248 function IsCachedUpdates: Boolean;
249 procedure SetCachedUpdates(Value: Boolean);
250 function IsPendingUpdates: Boolean; virtual;
252 procedure PostUpdates; virtual;
253 procedure CancelUpdates; virtual;
254 procedure RevertRecord; virtual;
255 procedure MoveToInitialRow; virtual;
256 procedure PostUpdatesCached; virtual;
257 procedure DisposeCachedUpdates; virtual;
261 Implements Abstract cached ResultSet. This class should be extended
262 with database specific logic to form SQL data manipulation statements.
264 TZCachedResultSet = class(TZAbstractCachedResultSet)
266 FResultSet: IZResultSet;
268 procedure Open; override;
269 function Fetch: Boolean; virtual;
270 procedure FetchAll; virtual;
272 property ResultSet: IZResultSet read FResultSet write FResultSet;
274 constructor Create(ResultSet: IZResultSet; SQL: string;
275 Resolver: IZCachedResolver; ConSettings: PZConSettings);
276 destructor Destroy; override;
278 procedure Close; override;
279 function GetMetaData: IZResultSetMetaData; override;
281 function IsAfterLast: Boolean; override;
282 function IsLast: Boolean; override;
283 procedure AfterLast; override;
284 function Last: Boolean; override;
285 function MoveAbsolute(Row: Integer): Boolean; override;
290 uses ZMessages, ZDbcResultSetMetadata, ZDbcGenericResolver, ZDbcUtils, ZEncoding;
292 { TZAbstractCachedResultSet }
295 Creates this object and assignes the main properties.
296 @param Statement an SQL statement object.
297 @param SQL an SQL query.
299 constructor TZAbstractCachedResultSet.CreateWithStatement(SQL: string;
300 Statement: IZStatement; ConSettings: PZConSettings);
302 inherited Create(Statement, SQL, nil, ConSettings);
303 FCachedUpdates := False;
307 Creates this object and assignes the main properties.
308 @param SQL an SQL query.
309 @param ColumnsInfo a columns info for cached rows.
311 constructor TZAbstractCachedResultSet.CreateWithColumns(
312 ColumnsInfo: TObjectList; SQL: string; ConSettings: PZConSettings);
314 inherited Create(nil, SQL, nil, ConSettings);
316 CopyColumnsInfo(ColumnsInfo, Self.ColumnsInfo);
317 FCachedUpdates := False;
322 Destroys this object and cleanups the memory.
324 destructor TZAbstractCachedResultSet.Destroy;
327 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
328 FNativeResolver := nil;
329 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
334 Checks for availability of the cached buffer.
336 procedure TZAbstractCachedResultSet.CheckAvailable;
339 if (FRowAccessor = nil) or (FRowAccessor.RowBuffer = nil) then
340 raise EZSQLException.Create(SRowDataIsNotAvailable);
344 Checks is the cached buffer updatable.
346 procedure TZAbstractCachedResultSet.CheckUpdatable;
349 if ResultSetConcurrency <> rcUpdatable then
350 RaiseReadOnlyException;
354 Generates the next row index value.
355 @return the new generated row index.
357 function TZAbstractCachedResultSet.GetNextRowIndex: Integer;
359 Result := FNextRowIndex;
364 Finds a row with specified index among list of rows.
365 @param RowsList a list of rows.
366 @param Index a row index.
367 @return a found row buffer of <code>null</code> otherwise.
369 function TZAbstractCachedResultSet.LocateRow(RowsList: TList;
370 RowIndex: Integer): Integer;
375 for I := 0 to RowsList.Count - 1 do
377 if PZRowBuffer(RowsList[I]).Index = RowIndex then
386 Appends a row to the list of rows if such row is not exist.
387 @param Row a row buffer.
388 @return an appended row buffer.
390 function TZAbstractCachedResultSet.AppendRow(Row: PZRowBuffer): PZRowBuffer;
392 if LocateRow(FInitialRowsList, Row.Index) < 0 then
394 FRowAccessor.AllocBuffer(Result);
395 FRowAccessor.CopyBuffer(Row, Result);
396 FInitialRowsList.Add(Result);
397 FCurrentRowsList.Add(Row);
404 Prepares the current selected row for updates.
406 procedure TZAbstractCachedResultSet.PrepareRowForUpdates;
408 if (RowAccessor.RowBuffer = FSelectedRow) and (FSelectedRow <> FUpdatedRow) then
410 FSelectedRow := FUpdatedRow;
411 RowAccessor.RowBuffer := FSelectedRow;
412 RowAccessor.CloneFrom(PZRowBuffer(FRowsList[RowNo - 1]));
417 Calculates column default values..
418 @param RowAccessor a row accessor which contains new column values.
420 procedure TZAbstractCachedResultSet.CalculateRowDefaults(
421 RowAccessor: TZRowAccessor);
423 {$IFNDEF DISABLE_CHECKING}
424 if Resolver = nil then
425 raise EZSQLException.Create(SResolverIsNotSpecified);
427 Resolver.CalculateDefaults(Self, RowAccessor);
431 Post changes to database server.
432 @param OldRowAccessor a row accessor which contains old column values.
433 @param NewRowAccessor a row accessor which contains new or updated
436 procedure TZAbstractCachedResultSet.PostRowUpdates(OldRowAccessor,
437 NewRowAccessor: TZRowAccessor);
439 {$IFNDEF DISABLE_CHECKING}
440 if Resolver = nil then
441 raise EZSQLException.Create(SResolverIsNotSpecified);
443 Resolver.PostUpdates(Self, NewRowAccessor.RowBuffer.UpdateType,
444 OldRowAccessor, NewRowAccessor);
448 Gets a cached updates resolver object.
449 @return a cached updates resolver object.
451 function TZAbstractCachedResultSet.GetResolver: IZCachedResolver;
457 Sets a new cached updates resolver object.
458 @param Resolver a cached updates resolver object.
460 procedure TZAbstractCachedResultSet.SetResolver(Resolver: IZCachedResolver);
462 FResolver := Resolver;
463 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
464 if FNativeResolver = nil then
465 FNativeResolver := Resolver;
466 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
468 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
470 Gets a Native cached updates resolver object.
471 @return a Native cached updates resolver object.
473 function TZAbstractCachedResultSet.GetNativeResolver: IZCachedResolver;
475 Result := FNativeResolver;
477 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
480 Checks is the cached updates mode turned on.
481 @return <code>True</code> if the cached updates mode turned on.
483 function TZAbstractCachedResultSet.IsCachedUpdates: Boolean;
485 Result := FCachedUpdates;
489 Switched the cached updates mode.
490 @param Value boolean flag which turns on/off the cached updates mode.
492 procedure TZAbstractCachedResultSet.SetCachedUpdates(Value: Boolean);
494 if FCachedUpdates <> Value then
496 FCachedUpdates := Value;
497 if not FCachedUpdates then
503 Checks is cached updates pending.
504 @return <code>True</code> if the cached updates pending.
506 function TZAbstractCachedResultSet.IsPendingUpdates: Boolean;
508 Result := FInitialRowsList.Count > 0;
512 Moves to the current row with initial column values.
514 procedure TZAbstractCachedResultSet.MoveToInitialRow;
519 if (RowNo >= 1) and (RowNo <= LastRowNo) and (FSelectedRow <> nil) then
521 Index := LocateRow(FInitialRowsList, FSelectedRow.Index);
524 FSelectedRow := FInitialRowsList[Index];
525 FRowAccessor.RowBuffer := FSelectedRow;
529 FRowAccessor.RowBuffer := nil;
533 Posts all saved updates to the server.
535 procedure TZAbstractCachedResultSet.PostUpdates;
538 if FInitialRowsList.Count > 0 then
540 while FInitialRowsList.Count > 0 do
542 OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[0]);
543 NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[0]);
545 { Updates default field values. }
546 if NewRowAccessor.RowBuffer.UpdateType = utInserted then
547 CalculateRowDefaults(NewRowAccessor);
549 { Posts row updates and processes the exceptions. }
550 PostRowUpdates(OldRowAccessor, NewRowAccessor);
552 { If post was Ok - update the row update type. }
553 if NewRowAccessor.RowBuffer.UpdateType <> utDeleted then
555 NewRowAccessor.RowBuffer.UpdateType := utUnmodified;
556 if (FSelectedRow <> nil)
557 and (FSelectedRow.Index = NewRowAccessor.RowBuffer.Index) then
558 FSelectedRow.UpdateType := utUnmodified;
561 { Removes cached rows. }
562 OldRowAccessor.Dispose;
563 FInitialRowsList.Delete(0);
564 FCurrentRowsList.Delete(0);
570 Posts all saved updates to the server but keeps them cached.
572 procedure TZAbstractCachedResultSet.PostUpdatesCached;
577 if FInitialRowsList.Count > 0 then
580 while i < FInitialRowsList.Count do
582 OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[i]);
583 NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[i]);
586 { Updates default field values. }
587 if NewRowAccessor.RowBuffer.UpdateType = utInserted then
588 CalculateRowDefaults(NewRowAccessor);
590 { Posts row updates. }
591 PostRowUpdates(OldRowAccessor, NewRowAccessor);
597 Frees the updates and marks records as unmodified. Complements
600 procedure TZAbstractCachedResultSet.DisposeCachedUpdates;
602 while FInitialRowsList.Count > 0 do
604 OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[0]);
605 NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[0]);
607 if NewRowAccessor.RowBuffer.UpdateType <> utDeleted then
609 NewRowAccessor.RowBuffer.UpdateType := utUnmodified;
610 if (FSelectedRow <> nil)
611 and (FSelectedRow.Index = NewRowAccessor.RowBuffer.Index) then
612 FSelectedRow.UpdateType := utUnmodified;
615 { Remove cached rows. }
616 OldRowAccessor.Dispose;
617 FInitialRowsList.Delete(0);
618 FCurrentRowsList.Delete(0);
623 Cancels updates for all rows.
625 procedure TZAbstractCachedResultSet.CancelUpdates;
627 InitialRow, CurrentRow: PZRowBuffer;
630 while FInitialRowsList.Count > 0 do
632 InitialRow := PZRowBuffer(FInitialRowsList[0]);
633 CurrentRow := PZRowBuffer(FCurrentRowsList[0]);
635 if CurrentRow.UpdateType = utInserted then
636 InitialRow.UpdateType := utDeleted;
638 FRowAccessor.CopyBuffer(InitialRow, CurrentRow);
639 if (FSelectedRow = FUpdatedRow)
640 and (FSelectedRow.Index = InitialRow.Index) then
641 FRowAccessor.CopyBuffer(InitialRow, FSelectedRow);
643 FRowAccessor.DisposeBuffer(InitialRow);
644 FInitialRowsList.Delete(0);
645 FCurrentRowsList.Delete(0);
650 Cancels updates for the current row.
652 procedure TZAbstractCachedResultSet.RefreshRow;
654 if Resolver = nil then
655 raise EZSQLException.Create(SResolverIsNotSpecified);
656 Resolver.RefreshCurrentRow(Self,RowAccessor);
659 procedure TZAbstractCachedResultSet.RevertRecord;
662 InitialRow, CurrentRow: PZRowBuffer;
665 if (RowNo >= 1) and (RowNo <= LastRowNo) then
667 Index := LocateRow(FInitialRowsList, FSelectedRow.Index);
670 InitialRow := PZRowBuffer(FInitialRowsList[Index]);
671 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
673 if CurrentRow.UpdateType = utInserted then
674 InitialRow.UpdateType := utDeleted;
675 FRowAccessor.CopyBuffer(InitialRow, CurrentRow);
676 if (FSelectedRow = FUpdatedRow) then
677 FRowAccessor.CopyBuffer(InitialRow, FSelectedRow);
679 FRowAccessor.DisposeBuffer(InitialRow);
680 FInitialRowsList.Delete(Index);
681 FCurrentRowsList.Delete(Index);
687 Opens this recordset.
689 procedure TZAbstractCachedResultSet.Open;
692 raise EZSQLException.Create(SResultsetIsAlreadyOpened);
694 FRowsList := TList.Create;
695 FInitialRowsList := TList.Create;
696 FCurrentRowsList := TList.Create;
698 FRowAccessor := TZRowAccessor.Create(ColumnsInfo, ConSettings);
699 FOldRowAccessor := TZRowAccessor.Create(ColumnsInfo, ConSettings);
700 FNewRowAccessor := TZRowAccessor.Create(ColumnsInfo, ConSettings);
702 FRowAccessor.AllocBuffer(FUpdatedRow);
703 FRowAccessor.AllocBuffer(FInsertedRow);
708 if (Resolver = nil) and (GetConcurrency = rcUpdatable) then
709 Resolver := TZGenericCachedResolver.Create(GetStatement, GetMetadata);
715 Releases this <code>ResultSet</code> object's database and
716 JDBC resources immediately instead of waiting for
717 this to happen when it is automatically closed.
719 <P><B>Note:</B> A <code>ResultSet</code> object
720 is automatically closed by the
721 <code>Statement</code> object that generated it when
722 that <code>Statement</code> object is closed,
723 re-executed, or is used to retrieve the next result from a
724 sequence of multiple results. A <code>ResultSet</code> object
725 is also automatically closed when it is garbage collected.
727 procedure TZAbstractCachedResultSet.Close;
733 if Assigned(FRowAccessor) then
735 for I := 0 to FRowsList.Count - 1 do
736 FRowAccessor.DisposeBuffer(PZRowBuffer(FRowsList[I]));
737 for I := 0 to FInitialRowsList.Count - 1 do
738 FRowAccessor.DisposeBuffer(PZRowBuffer(FInitialRowsList[I]));
740 FRowAccessor.DisposeBuffer(FUpdatedRow);
742 FRowAccessor.DisposeBuffer(FInsertedRow);
746 FreeAndNil(FRowsList);
747 FreeAndNil(FInitialRowsList);
748 FreeAndNil(FCurrentRowsList);
750 FreeAndNil(FRowAccessor);
751 FreeAndNil(FOldRowAccessor);
752 FreeAndNil(FNewRowAccessor);
756 //======================================================================
757 // Methods for accessing results by column index
758 //======================================================================
761 Indicates if the value of the designated column in the current row
762 of this <code>ResultSet</code> object is Null.
764 @param columnIndex the first column is 1, the second is 2, ...
765 @return if the value is SQL <code>NULL</code>, the
766 value returned is <code>true</code>. <code>false</code> otherwise.
768 function TZAbstractCachedResultSet.IsNull(ColumnIndex: Integer): Boolean;
770 {$IFNDEF DISABLE_CHECKING}
773 Result := FRowAccessor.IsNull(ColumnIndex);
777 Gets the value of the designated column in the current row
778 of this <code>ResultSet</code> object as
779 a <code>PAnsiChar</code> in the Delphi programming language.
781 @param columnIndex the first column is 1, the second is 2, ...
782 @return the column value; if the value is SQL <code>NULL</code>, the
783 value returned is <code>null</code>
785 function TZAbstractCachedResultSet.GetPChar(ColumnIndex: Integer): PChar;
787 {$IFNDEF DISABLE_CHECKING}
790 Result := FRowAccessor.GetPChar(ColumnIndex, LastWasNull);
794 Gets the value of the designated column in the current row
795 of this <code>ResultSet</code> object as
796 a <code>String</code> in the Java programming language.
798 @param columnIndex the first column is 1, the second is 2, ...
799 @return the column value; if the value is SQL <code>NULL</code>, the
800 value returned is <code>null</code>
802 function TZAbstractCachedResultSet.GetString(ColumnIndex: Integer): String;
804 {$IFNDEF DISABLE_CHECKING}
807 Result := FRowAccessor.GetString(ColumnIndex, LastWasNull);
811 Gets the value of the designated column in the current row
812 of this <code>ResultSet</code> object as
813 a <code>Widestring</code> in the Java programming language.
815 @param columnIndex the first column is 1, the second is 2, ...
816 @return the column value; if the value is SQL <code>NULL</code>, the
817 value returned is <code>null</code>
819 function TZAbstractCachedResultSet.GetUnicodeString(ColumnIndex: Integer): Widestring;
821 {$IFNDEF DISABLE_CHECKING}
824 Result := FRowAccessor.GetUnicodeString(ColumnIndex, LastWasNull);
828 Gets the value of the designated column in the current row
829 of this <code>ResultSet</code> object as
830 a <code>boolean</code> in the Java programming language.
832 @param columnIndex the first column is 1, the second is 2, ...
833 @return the column value; if the value is SQL <code>NULL</code>, the
834 value returned is <code>false</code>
836 function TZAbstractCachedResultSet.GetBoolean(ColumnIndex: Integer): Boolean;
838 {$IFNDEF DISABLE_CHECKING}
841 Result := FRowAccessor.GetBoolean(ColumnIndex, LastWasNull);
845 Gets the value of the designated column in the current row
846 of this <code>ResultSet</code> object as
847 a <code>byte</code> in the Java programming language.
849 @param columnIndex the first column is 1, the second is 2, ...
850 @return the column value; if the value is SQL <code>NULL</code>, the
851 value returned is <code>0</code>
853 function TZAbstractCachedResultSet.GetByte(ColumnIndex: Integer): Byte;
855 {$IFNDEF DISABLE_CHECKING}
858 Result := FRowAccessor.GetByte(ColumnIndex, LastWasNull);
862 Gets the value of the designated column in the current row
863 of this <code>ResultSet</code> object as
864 a <code>short</code> in the Java programming language.
866 @param columnIndex the first column is 1, the second is 2, ...
867 @return the column value; if the value is SQL <code>NULL</code>, the
868 value returned is <code>0</code>
870 function TZAbstractCachedResultSet.GetShort(ColumnIndex: Integer): SmallInt;
872 {$IFNDEF DISABLE_CHECKING}
875 Result := FRowAccessor.GetShort(ColumnIndex, LastWasNull);
879 Gets the value of the designated column in the current row
880 of this <code>ResultSet</code> object as
881 an <code>int</code> in the Java programming language.
883 @param columnIndex the first column is 1, the second is 2, ...
884 @return the column value; if the value is SQL <code>NULL</code>, the
885 value returned is <code>0</code>
887 function TZAbstractCachedResultSet.GetInt(ColumnIndex: Integer): Integer;
889 {$IFNDEF DISABLE_CHECKING}
892 Result := FRowAccessor.GetInt(ColumnIndex, LastWasNull);
896 Gets the value of the designated column in the current row
897 of this <code>ResultSet</code> object as
898 a <code>long</code> in the Java programming language.
900 @param columnIndex the first column is 1, the second is 2, ...
901 @return the column value; if the value is SQL <code>NULL</code>, the
902 value returned is <code>0</code>
904 function TZAbstractCachedResultSet.GetLong(ColumnIndex: Integer): Int64;
906 {$IFNDEF DISABLE_CHECKING}
909 Result := FRowAccessor.GetLong(ColumnIndex, LastWasNull);
913 Gets the value of the designated column in the current row
914 of this <code>ResultSet</code> object as
915 a <code>float</code> in the Java programming language.
917 @param columnIndex the first column is 1, the second is 2, ...
918 @return the column value; if the value is SQL <code>NULL</code>, the
919 value returned is <code>0</code>
921 function TZAbstractCachedResultSet.GetFloat(ColumnIndex: Integer): Single;
923 {$IFNDEF DISABLE_CHECKING}
926 Result := FRowAccessor.GetFloat(ColumnIndex, LastWasNull);
930 Gets the value of the designated column in the current row
931 of this <code>ResultSet</code> object as
932 a <code>double</code> in the Java programming language.
934 @param columnIndex the first column is 1, the second is 2, ...
935 @return the column value; if the value is SQL <code>NULL</code>, the
936 value returned is <code>0</code>
938 function TZAbstractCachedResultSet.GetDouble(ColumnIndex: Integer): Double;
940 {$IFNDEF DISABLE_CHECKING}
943 Result := FRowAccessor.GetDouble(ColumnIndex, LastWasNull);
947 Gets the value of the designated column in the current row
948 of this <code>ResultSet</code> object as
949 a <code>java.sql.BigDecimal</code> in the Java programming language.
951 @param columnIndex the first column is 1, the second is 2, ...
952 @param scale the number of digits to the right of the decimal point
953 @return the column value; if the value is SQL <code>NULL</code>, the
954 value returned is <code>null</code>
956 function TZAbstractCachedResultSet.GetBigDecimal(ColumnIndex: Integer): Extended;
958 {$IFNDEF DISABLE_CHECKING}
961 Result := FRowAccessor.GetBigDecimal(ColumnIndex, LastWasNull);
965 Gets the value of the designated column in the current row
966 of this <code>ResultSet</code> object as
967 a <code>byte</code> array in the Java programming language.
968 The bytes represent the raw values returned by the driver.
970 @param columnIndex the first column is 1, the second is 2, ...
971 @return the column value; if the value is SQL <code>NULL</code>, the
972 value returned is <code>null</code>
974 function TZAbstractCachedResultSet.GetBytes(ColumnIndex: Integer): TByteDynArray;
976 {$IFNDEF DISABLE_CHECKING}
979 Result := FRowAccessor.GetBytes(ColumnIndex, LastWasNull);
983 Gets the value of the designated column in the current row
984 of this <code>ResultSet</code> object as
985 a <code>java.sql.Date</code> object in the Java programming language.
987 @param columnIndex the first column is 1, the second is 2, ...
988 @return the column value; if the value is SQL <code>NULL</code>, the
989 value returned is <code>null</code>
991 function TZAbstractCachedResultSet.GetDate(ColumnIndex: Integer): TDateTime;
993 {$IFNDEF DISABLE_CHECKING}
996 Result := FRowAccessor.GetDate(ColumnIndex, LastWasNull);
1000 Gets the value of the designated column in the current row
1001 of this <code>ResultSet</code> object as
1002 a <code>java.sql.Time</code> object in the Java programming language.
1004 @param columnIndex the first column is 1, the second is 2, ...
1005 @return the column value; if the value is SQL <code>NULL</code>, the
1006 value returned is <code>null</code>
1008 function TZAbstractCachedResultSet.GetTime(ColumnIndex: Integer): TDateTime;
1010 {$IFNDEF DISABLE_CHECKING}
1013 Result := FRowAccessor.GetTime(ColumnIndex, LastWasNull);
1017 Gets the value of the designated column in the current row
1018 of this <code>ResultSet</code> object as
1019 a <code>java.sql.Timestamp</code> object in the Java programming language.
1021 @param columnIndex the first column is 1, the second is 2, ...
1022 @return the column value; if the value is SQL <code>NULL</code>, the
1023 value returned is <code>null</code>
1024 @exception SQLException if a database access error occurs
1026 function TZAbstractCachedResultSet.GetTimestamp(ColumnIndex: Integer): TDateTime;
1028 {$IFNDEF DISABLE_CHECKING}
1031 Result := FRowAccessor.GetTimestamp(ColumnIndex, LastWasNull);
1035 Returns the value of the designated column in the current row
1036 of this <code>ResultSet</code> object as a <code>Blob</code> object
1037 in the Java programming language.
1039 @param ColumnIndex the first column is 1, the second is 2, ...
1040 @return a <code>Blob</code> object representing the SQL <code>BLOB</code> value in
1041 the specified column
1043 function TZAbstractCachedResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
1045 {$IFNDEF DISABLE_CHECKING}
1048 Result := FRowAccessor.GetBlob(ColumnIndex, LastWasNull);
1052 Gets the DefaultExpression value of the designated column in the current row
1053 of this <code>ResultSet</code> object as
1054 a <code>String</code>.
1056 @param columnIndex the first column is 1, the second is 2, ...
1057 @return the DefaultExpression value
1059 function TZAbstractCachedResultSet.GetDefaultExpression(ColumnIndex: Integer): string;
1061 {$IFNDEF DISABLE_CHECKING}
1064 Result := FRowAccessor.GetColumnDefaultExpression(ColumnIndex);
1067 //---------------------------------------------------------------------
1069 //---------------------------------------------------------------------
1072 Gives a nullable column a null value.
1074 The <code>updateXXX</code> methods are used to update column values in the
1075 current row or the insert row. The <code>updateXXX</code> methods do not
1076 update the underlying database; instead the <code>updateRow</code>
1077 or <code>insertRow</code> methods are called to update the database.
1079 @param columnIndex the first column is 1, the second is 2, ...
1081 procedure TZAbstractCachedResultSet.UpdateNull(ColumnIndex: Integer);
1083 {$IFNDEF DISABLE_CHECKING}
1086 PrepareRowForUpdates;
1087 FRowAccessor.SetNull(ColumnIndex);
1091 Updates the designated column with a <code>boolean</code> value.
1092 The <code>updateXXX</code> methods are used to update column values in the
1093 current row or the insert row. The <code>updateXXX</code> methods do not
1094 update the underlying database; instead the <code>updateRow</code> or
1095 <code>insertRow</code> methods are called to update the database.
1097 @param columnIndex the first column is 1, the second is 2, ...
1098 @param x the new column value
1100 procedure TZAbstractCachedResultSet.UpdateBoolean(ColumnIndex: Integer;
1103 {$IFNDEF DISABLE_CHECKING}
1106 PrepareRowForUpdates;
1107 FRowAccessor.SetBoolean(ColumnIndex, Value);
1111 Updates the designated column with a <code>byte</code> value.
1112 The <code>updateXXX</code> methods are used to update column values in the
1113 current row or the insert row. The <code>updateXXX</code> methods do not
1114 update the underlying database; instead the <code>updateRow</code> or
1115 <code>insertRow</code> methods are called to update the database.
1117 @param columnIndex the first column is 1, the second is 2, ...
1118 @param x the new column value
1120 procedure TZAbstractCachedResultSet.UpdateByte(ColumnIndex: Integer;
1123 {$IFNDEF DISABLE_CHECKING}
1126 PrepareRowForUpdates;
1127 FRowAccessor.SetByte(ColumnIndex, Value);
1131 Updates the designated column with a <code>short</code> value.
1132 The <code>updateXXX</code> methods are used to update column values in the
1133 current row or the insert row. The <code>updateXXX</code> methods do not
1134 update the underlying database; instead the <code>updateRow</code> or
1135 <code>insertRow</code> methods are called to update the database.
1137 @param columnIndex the first column is 1, the second is 2, ...
1138 @param x the new column value
1140 procedure TZAbstractCachedResultSet.UpdateShort(ColumnIndex: Integer;
1143 {$IFNDEF DISABLE_CHECKING}
1146 PrepareRowForUpdates;
1147 FRowAccessor.SetShort(ColumnIndex, Value);
1151 Updates the designated column with an <code>int</code> value.
1152 The <code>updateXXX</code> methods are used to update column values in the
1153 current row or the insert row. The <code>updateXXX</code> methods do not
1154 update the underlying database; instead the <code>updateRow</code> or
1155 <code>insertRow</code> methods are called to update the database.
1157 @param columnIndex the first column is 1, the second is 2, ...
1158 @param x the new column value
1160 procedure TZAbstractCachedResultSet.UpdateInt(ColumnIndex, Value: Integer);
1162 {$IFNDEF DISABLE_CHECKING}
1165 PrepareRowForUpdates;
1166 FRowAccessor.SetInt(ColumnIndex, Value);
1170 Updates the designated column with a <code>long</code> value.
1171 The <code>updateXXX</code> methods are used to update column values in the
1172 current row or the insert row. The <code>updateXXX</code> methods do not
1173 update the underlying database; instead the <code>updateRow</code> or
1174 <code>insertRow</code> methods are called to update the database.
1176 @param columnIndex the first column is 1, the second is 2, ...
1177 @param x the new column value
1179 procedure TZAbstractCachedResultSet.UpdateLong(ColumnIndex: Integer;
1182 {$IFNDEF DISABLE_CHECKING}
1185 PrepareRowForUpdates;
1186 FRowAccessor.SetLong(ColumnIndex, Value);
1190 Updates the designated column with a <code>float</code> value.
1191 The <code>updateXXX</code> methods are used to update column values in the
1192 current row or the insert row. The <code>updateXXX</code> methods do not
1193 update the underlying database; instead the <code>updateRow</code> or
1194 <code>insertRow</code> methods are called to update the database.
1196 @param columnIndex the first column is 1, the second is 2, ...
1197 @param x the new column value
1199 procedure TZAbstractCachedResultSet.UpdateFloat(ColumnIndex: Integer;
1202 {$IFNDEF DISABLE_CHECKING}
1205 PrepareRowForUpdates;
1206 FRowAccessor.SetFloat(ColumnIndex, Value);
1210 Updates the designated column with a <code>double</code> value.
1211 The <code>updateXXX</code> methods are used to update column values in the
1212 current row or the insert row. The <code>updateXXX</code> methods do not
1213 update the underlying database; instead the <code>updateRow</code> or
1214 <code>insertRow</code> methods are called to update the database.
1216 @param columnIndex the first column is 1, the second is 2, ...
1217 @param x the new column value
1219 procedure TZAbstractCachedResultSet.UpdateDouble(ColumnIndex: Integer;
1222 {$IFNDEF DISABLE_CHECKING}
1225 PrepareRowForUpdates;
1226 FRowAccessor.SetDouble(ColumnIndex, Value);
1230 Updates the designated column with a <code>java.math.BigDecimal</code>
1232 The <code>updateXXX</code> methods are used to update column values in the
1233 current row or the insert row. The <code>updateXXX</code> methods do not
1234 update the underlying database; instead the <code>updateRow</code> or
1235 <code>insertRow</code> methods are called to update the database.
1237 @param columnIndex the first column is 1, the second is 2, ...
1238 @param x the new column value
1240 procedure TZAbstractCachedResultSet.UpdateBigDecimal(ColumnIndex: Integer;
1243 {$IFNDEF DISABLE_CHECKING}
1246 PrepareRowForUpdates;
1247 FRowAccessor.SetBigDecimal(ColumnIndex, Value);
1251 Updates the designated column with a <code>String</code> value.
1252 The <code>updateXXX</code> methods are used to update column values in the
1253 current row or the insert row. The <code>updateXXX</code> methods do not
1254 update the underlying database; instead the <code>updateRow</code> or
1255 <code>insertRow</code> methods are called to update the database.
1257 @param columnIndex the first column is 1, the second is 2, ...
1258 @param x the new column value
1260 procedure TZAbstractCachedResultSet.UpdatePChar(ColumnIndex: Integer;
1263 {$IFNDEF DISABLE_CHECKING}
1266 PrepareRowForUpdates;
1267 FRowAccessor.SetPChar(ColumnIndex, Value);
1271 Updates the designated column with a <code>String</code> value.
1272 The <code>updateXXX</code> methods are used to update column values in the
1273 current row or the insert row. The <code>updateXXX</code> methods do not
1274 update the underlying database; instead the <code>updateRow</code> or
1275 <code>insertRow</code> methods are called to update the database.
1277 @param columnIndex the first column is 1, the second is 2, ...
1278 @param x the new column value
1280 procedure TZAbstractCachedResultSet.UpdateString(ColumnIndex: Integer;
1281 const Value: String);
1283 {$IFNDEF DISABLE_CHECKING}
1286 PrepareRowForUpdates;
1287 FRowAccessor.SetString(ColumnIndex, Value);
1291 Updates the designated column with a <code>Widestring</code> value.
1292 The <code>updateXXX</code> methods are used to update column values in the
1293 current row or the insert row. The <code>updateXXX</code> methods do not
1294 update the underlying database; instead the <code>updateRow</code> or
1295 <code>insertRow</code> methods are called to update the database.
1297 @param columnIndex the first column is 1, the second is 2, ...
1298 @param x the new column value
1300 procedure TZAbstractCachedResultSet.UpdateUnicodeString(ColumnIndex: Integer;
1301 const Value: WideString);
1303 {$IFNDEF DISABLE_CHECKING}
1306 PrepareRowForUpdates;
1307 FRowAccessor.SetUnicodeString(ColumnIndex, Value);
1311 Updates the designated column with a <code>byte</code> array value.
1312 The <code>updateXXX</code> methods are used to update column values in the
1313 current row or the insert row. The <code>updateXXX</code> methods do not
1314 update the underlying database; instead the <code>updateRow</code> or
1315 <code>insertRow</code> methods are called to update the database.
1317 @param columnIndex the first column is 1, the second is 2, ...
1318 @param x the new column value
1320 procedure TZAbstractCachedResultSet.UpdateBytes(ColumnIndex: Integer;
1321 const Value: TByteDynArray);
1323 {$IFNDEF DISABLE_CHECKING}
1326 PrepareRowForUpdates;
1327 FRowAccessor.SetBytes(ColumnIndex, Value);
1331 Updates the designated column with a <code>java.sql.Date</code> value.
1332 The <code>updateXXX</code> methods are used to update column values in the
1333 current row or the insert row. The <code>updateXXX</code> methods do not
1334 update the underlying database; instead the <code>updateRow</code> or
1335 <code>insertRow</code> methods are called to update the database.
1337 @param columnIndex the first column is 1, the second is 2, ...
1338 @param x the new column value
1340 procedure TZAbstractCachedResultSet.UpdateDate(ColumnIndex: Integer;
1343 {$IFNDEF DISABLE_CHECKING}
1346 PrepareRowForUpdates;
1347 FRowAccessor.SetDate(ColumnIndex, Value);
1351 Updates the designated column with a <code>java.sql.Time</code> value.
1352 The <code>updateXXX</code> methods are used to update column values in the
1353 current row or the insert row. The <code>updateXXX</code> methods do not
1354 update the underlying database; instead the <code>updateRow</code> or
1355 <code>insertRow</code> methods are called to update the database.
1357 @param columnIndex the first column is 1, the second is 2, ...
1358 @param x the new column value
1360 procedure TZAbstractCachedResultSet.UpdateTime(ColumnIndex: Integer;
1363 {$IFNDEF DISABLE_CHECKING}
1366 PrepareRowForUpdates;
1367 FRowAccessor.SetTime(ColumnIndex, Value);
1371 Updates the designated column with a <code>java.sql.Timestamp</code>
1373 The <code>updateXXX</code> methods are used to update column values in the
1374 current row or the insert row. The <code>updateXXX</code> methods do not
1375 update the underlying database; instead the <code>updateRow</code> or
1376 <code>insertRow</code> methods are called to update the database.
1378 @param columnIndex the first column is 1, the second is 2, ...
1379 @param x the new column value
1381 procedure TZAbstractCachedResultSet.UpdateTimestamp(ColumnIndex: Integer;
1384 {$IFNDEF DISABLE_CHECKING}
1387 PrepareRowForUpdates;
1388 FRowAccessor.SetTimestamp(ColumnIndex, Value);
1392 Updates the designated column with an ascii stream value.
1393 The <code>updateXXX</code> methods are used to update column values in the
1394 current row or the insert row. The <code>updateXXX</code> methods do not
1395 update the underlying database; instead the <code>updateRow</code> or
1396 <code>insertRow</code> methods are called to update the database.
1398 @param columnIndex the first column is 1, the second is 2, ...
1399 @param x the new column value
1401 procedure TZAbstractCachedResultSet.UpdateAsciiStream(ColumnIndex: Integer;
1404 {$IFNDEF DISABLE_CHECKING}
1407 PrepareRowForUpdates;
1408 FRowAccessor.SetAsciiStream(ColumnIndex, Value);
1412 Updates the designated column with a binary stream value.
1413 The <code>updateXXX</code> methods are used to update column values in the
1414 current row or the insert row. The <code>updateXXX</code> methods do not
1415 update the underlying database; instead the <code>updateRow</code> or
1416 <code>insertRow</code> methods are called to update the database.
1418 @param columnIndex the first column is 1, the second is 2, ...
1419 @param x the new column value
1420 @param length the length of the stream
1422 procedure TZAbstractCachedResultSet.UpdateBinaryStream(
1423 ColumnIndex: Integer; Value: TStream);
1425 {$IFNDEF DISABLE_CHECKING}
1428 PrepareRowForUpdates;
1429 FRowAccessor.SetBinaryStream(ColumnIndex, Value);
1433 Updates the designated column with a character stream value.
1434 The <code>updateXXX</code> methods are used to update column values in the
1435 current row or the insert row. The <code>updateXXX</code> methods do not
1436 update the underlying database; instead the <code>updateRow</code> or
1437 <code>insertRow</code> methods are called to update the database.
1439 @param columnIndex the first column is 1, the second is 2, ...
1440 @param x the new column value
1442 procedure TZAbstractCachedResultSet.UpdateUnicodeStream(
1443 ColumnIndex: Integer; Value: TStream);
1445 TempStream: TStream;
1447 {$IFNDEF DISABLE_CHECKING}
1450 PrepareRowForUpdates;
1452 Findout, wat's comming in! To avoid User-Bugs
1453 it is possible that a PAnsiChar OR a PWideChar was written into
1454 the Stream!!! And these chars could be trunced with changing the
1456 if Assigned(Value) then
1458 TempStream := GetValidatedUnicodeStream(TMemoryStream(Value).Memory, Value.Size, ConSettings, False);
1459 FRowAccessor.SetUnicodeStream(ColumnIndex, TempStream);
1463 FRowAccessor.SetUnicodeStream(ColumnIndex, nil);
1467 Updates the DefaultExpression of the designated column with a <code>String</code> value.
1468 This changes the behaviour of the RowAccessor used by the Resultset
1469 @param columnIndex the first column is 1, the second is 2, ...
1470 @param x the new DefaultExpression value for the column
1472 procedure TZAbstractCachedResultSet.UpdateDefaultExpression(ColumnIndex: Integer;
1473 const Value: string);
1475 FNewRowAccessor.SetColumnDefaultExpression(ColumnIndex, Value);
1478 //---------------------------------------------------------------------
1479 // Processing methods
1480 //---------------------------------------------------------------------
1483 Moves the cursor to the given row number in
1484 this <code>ResultSet</code> object.
1486 <p>If the row number is positive, the cursor moves to
1487 the given row number with respect to the
1488 beginning of the result set. The first row is row 1, the second
1489 is row 2, and so on.
1491 <p>If the given row number is negative, the cursor moves to
1492 an absolute row position with respect to
1493 the end of the result set. For example, calling the method
1494 <code>absolute(-1)</code> positions the
1495 cursor on the last row; calling the method <code>absolute(-2)</code>
1496 moves the cursor to the next-to-last row, and so on.
1498 <p>An attempt to position the cursor beyond the first/last row in
1499 the result set leaves the cursor before the first row or after
1502 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
1503 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
1504 is the same as calling <code>last()</code>.
1506 @return <code>true</code> if the cursor is on the result set;
1507 <code>false</code> otherwise
1509 function TZAbstractCachedResultSet.MoveAbsolute(Row: Integer): Boolean;
1511 {$IFNDEF DISABLE_CHECKING}
1513 if (ResultSetType = rtForwardOnly) and (Row < RowNo) then
1514 RaiseForwardOnlyException;
1517 if (Row >= 0) and (Row <= LastRowNo + 1) then
1520 if (Row >= 1) and (Row <= LastRowNo) then
1523 FSelectedRow := PZRowBuffer(FRowsList[Row - 1]);
1524 RowAccessor.RowBuffer := FSelectedRow;
1529 FSelectedRow := nil;
1530 RowAccessor.RowBuffer := FSelectedRow;
1538 Indicates whether the current row has been updated. The value returned
1539 depends on whether or not the result set can detect updates.
1541 @return <code>true</code> if the row has been visibly updated
1542 by the owner or another, and updates are detected
1544 function TZAbstractCachedResultSet.RowUpdated: Boolean;
1546 CurrentRow: PZRowBuffer;
1548 if (RowNo >= 1) and (RowNo <= LastRowNo) then
1550 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
1551 Result := CurrentRow^.UpdateType = utModified;
1558 Indicates whether the current row has had an insertion.
1559 The value returned depends on whether or not this
1560 <code>ResultSet</code> object can detect visible inserts.
1562 @return <code>true</code> if a row has had an insertion
1563 and insertions are detected; <code>false</code> otherwise
1565 function TZAbstractCachedResultSet.RowInserted: Boolean;
1567 CurrentRow: PZRowBuffer;
1569 if (RowNo >= 1) and (RowNo <= LastRowNo) then
1571 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
1572 Result := CurrentRow^.UpdateType = utInserted;
1579 Indicates whether a row has been deleted. A deleted row may leave
1580 a visible "hole" in a result set. This method can be used to
1581 detect holes in a result set. The value returned depends on whether
1582 or not this <code>ResultSet</code> object can detect deletions.
1584 @return <code>true</code> if a row was deleted and deletions are detected;
1585 <code>false</code> otherwise
1587 function TZAbstractCachedResultSet.RowDeleted: Boolean;
1589 UpdateType: TZRowUpdateType;
1591 if (RowNo >= 1) and (RowNo <= LastRowNo) then
1593 UpdateType := PZRowBuffer(FRowsList[RowNo - 1])^.UpdateType;
1594 Result := UpdateType = utDeleted;
1601 Inserts the contents of the insert row into this
1602 <code>ResultSet</code> object and into the database.
1603 The cursor must be on the insert row when this method is called.
1605 procedure TZAbstractCachedResultSet.InsertRow;
1607 TempRow: PZRowBuffer;
1611 { Creates a new row. }
1612 TempRow := FRowAccessor.RowBuffer;
1614 FRowAccessor.MoveFrom(FInsertedRow);
1615 FRowAccessor.RowBuffer^.UpdateType := utInserted;
1616 FRowAccessor.RowBuffer^.Index := GetNextRowIndex;
1618 AppendRow(FRowAccessor.RowBuffer);
1620 { Posts non-cached updates. }
1621 if not FCachedUpdates then
1628 { Restore the previous state. }
1629 FRowAccessor.DisposeBuffer(FInitialRowsList[FInitialRowsList.Count - 1]);
1630 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
1631 FRowAccessor.DisposeBuffer(FCurrentRowsList[FCurrentRowsList.Count - 1]);
1632 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
1633 FRowAccessor.RowBuffer := TempRow;
1635 { Reraises the exception. }
1636 RaiseSQLException(E);
1641 FRowsList.Add(FRowAccessor.RowBuffer);
1642 LastRowNo := FRowsList.Count;
1643 MoveAbsolute(LastRowNo);
1647 Updates the underlying database with the new contents of the
1648 current row of this <code>ResultSet</code> object.
1649 This method cannot be called when the cursor is on the insert row.
1651 procedure TZAbstractCachedResultSet.UpdateRow;
1654 if (RowNo < 1) or (RowNo > LastRowNo) then
1655 raise EZSQLException.Create(SCanNotUpdateEmptyRow);
1657 if PZRowBuffer(FRowsList[RowNo - 1]).UpdateType = utDeleted then
1658 raise EZSQLException.Create(SCanNotUpdateDeletedRow);
1660 if FSelectedRow <> FUpdatedRow then
1663 AppendRow(FRowsList[RowNo - 1]);
1665 FSelectedRow := PZRowBuffer(FRowsList[RowNo - 1]);
1666 FRowAccessor.CopyBuffer(FUpdatedRow, FSelectedRow);
1667 FRowAccessor.RowBuffer := FSelectedRow;
1668 if FSelectedRow.UpdateType = utUnmodified then
1669 FSelectedRow.UpdateType := utModified;
1671 { Posts non-cached updates. }
1672 if not FCachedUpdates then
1679 { Restore the previous state. }
1680 FRowAccessor.DisposeBuffer(FRowsList[RowNo - 1]);
1681 FRowsList[RowNo - 1] := FInitialRowsList[FInitialRowsList.Count - 1];
1682 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
1683 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
1685 FSelectedRow := PZRowBuffer(FRowsList[RowNo - 1]);
1686 FRowAccessor.RowBuffer := FSelectedRow;
1688 { Reraises the exception. }
1689 RaiseSQLException(E);
1696 Deletes the current row from this <code>ResultSet</code> object
1697 and from the underlying database. This method cannot be called when
1698 the cursor is on the insert row.
1700 procedure TZAbstractCachedResultSet.DeleteRow;
1703 if (RowNo < 1) or (RowNo > LastRowNo) or (FSelectedRow = nil) then
1704 raise EZSQLException.Create(SCanNotDeleteEmptyRow);
1706 if FSelectedRow^.UpdateType = utInserted then
1710 AppendRow(FRowsList[RowNo - 1]);
1712 FSelectedRow^.UpdateType := utDeleted;
1713 if FSelectedRow = FUpdatedRow then
1714 FRowAccessor.CopyBuffer(FUpdatedRow, FRowsList[RowNo - 1]);
1716 { Posts non-cached updates. }
1717 if not FCachedUpdates then
1724 { Restores the previous state. }
1725 FRowAccessor.DisposeBuffer(FRowsList[RowNo - 1]);
1726 FRowsList[RowNo - 1] := FInitialRowsList[FInitialRowsList.Count - 1];
1727 FSelectedRow := FRowsList[RowNo - 1];
1728 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
1729 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
1731 { Rethrows the exception. }
1732 RaiseSQLException(E);
1740 Cancels the updates made to the current row in this
1741 <code>ResultSet</code> object.
1742 This method may be called after calling an
1743 <code>updateXXX</code> method(s) and before calling
1744 the method <code>updateRow</code> to roll back
1745 the updates made to a row. If no updates have been made or
1746 <code>updateRow</code> has already been called, this method has no
1749 procedure TZAbstractCachedResultSet.CancelRowUpdates;
1751 MoveAbsolute(RowNo);
1755 Moves the cursor to the insert row. The current cursor position is
1756 remembered while the cursor is positioned on the insert row.
1758 The insert row is a special row associated with an updatable
1759 result set. It is essentially a buffer where a new row may
1760 be constructed by calling the <code>updateXXX</code> methods prior to
1761 inserting the row into the result set.
1763 Only the <code>updateXXX</code>, <code>getXXX</code>,
1764 and <code>insertRow</code> methods may be
1765 called when the cursor is on the insert row. All of the columns in
1766 a result set must be given a value each time this method is
1767 called before calling <code>insertRow</code>.
1768 An <code>updateXXX</code> method must be called before a
1769 <code>getXXX</code> method can be called on a column value.
1771 procedure TZAbstractCachedResultSet.MoveToInsertRow;
1774 FRowAccessor.RowBuffer := FInsertedRow;
1778 Moves the cursor to the remembered cursor position, usually the
1779 current row. This method has no effect if the cursor is not on
1782 procedure TZAbstractCachedResultSet.MoveToCurrentRow;
1785 if (RowNo >= 1) and (RowNo <= LastRowNo) then
1786 FRowAccessor.RowBuffer := FSelectedRow
1788 FRowAccessor.RowBuffer := nil;
1792 Compares fields from two row buffers.
1793 @param Row1 the first row buffer to compare.
1794 @param Row2 the second row buffer to compare.
1795 @param ColumnIndices column indices to compare.
1796 @param ColumnDirs compare direction for each columns.
1798 function TZAbstractCachedResultSet.CompareRows(Row1, Row2: Integer;
1799 const ColumnIndices: TIntegerDynArray; const ColumnDirs: TBooleanDynArray): Integer;
1801 RowBuffer1, RowBuffer2: PZRowBuffer;
1803 {$IFNDEF DISABLE_CHECKING}
1804 if ResultSetType = rtForwardOnly then
1805 RaiseForwardOnlyException;
1807 RowBuffer1 := PZRowBuffer(FRowsList[Row1 - 1]);
1808 RowBuffer2 := PZRowBuffer(FRowsList[Row2 - 1]);
1809 Result := FRowAccessor.CompareBuffers(RowBuffer1, RowBuffer2,
1810 ColumnIndices, ColumnDirs);
1813 { TZCachedResultSet }
1816 Creates this object and assignes the main properties.
1817 @param ResultSet a wrapped resultset object.
1818 @param Resolver a cached updates resolver object.
1820 constructor TZCachedResultSet.Create(ResultSet: IZResultSet; SQL: string;
1821 Resolver: IZCachedResolver; ConSettings: PZConSettings);
1823 inherited Create(ResultSet.GetStatement, SQL, nil, ConSettings);
1824 FResultSet := ResultSet;
1825 FResolver := Resolver;
1826 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
1827 FNativeResolver := Resolver;
1828 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
1833 Destroys this object and cleanups the memory.
1835 destructor TZCachedResultSet.Destroy;
1841 Fetches one row from the wrapped result set object.
1842 @return <code>True</code> if row was successfuly fetched
1843 or <code>False</code> otherwise.
1845 function TZCachedResultSet.Fetch: Boolean;
1848 TempRow: PZRowBuffer;
1850 Result := FResultSet.Next;
1851 if not Result or ((MaxRows > 0) and (LastRowNo >= MaxRows)) then
1854 TempRow := RowAccessor.RowBuffer;
1857 RowAccessor.RowBuffer.Index := GetNextRowIndex;
1858 RowAccessor.RowBuffer.UpdateType := utUnmodified;
1860 for I := 1 to ColumnsInfo.Count do
1862 case TZColumnInfo(ColumnsInfo[I - 1]).ColumnType of
1863 stBoolean: RowAccessor.SetBoolean(I, ResultSet.GetBoolean(I));
1864 stByte: RowAccessor.SetByte(I, ResultSet.GetByte(I));
1865 stShort: RowAccessor.SetShort(I, ResultSet.GetShort(I));
1866 stInteger: RowAccessor.SetInt(I, ResultSet.GetInt(I));
1867 stLong: RowAccessor.SetLong(I, ResultSet.GetLong(I));
1868 stFloat: RowAccessor.SetFloat(I, ResultSet.GetFloat(I));
1869 stDouble: RowAccessor.SetDouble(I, ResultSet.GetDouble(I));
1870 stBigDecimal: RowAccessor.SetBigDecimal(I, ResultSet.GetBigDecimal(I));
1871 stString: RowAccessor.SetString(I, ResultSet.GetString(I));
1872 stUnicodeString: RowAccessor.SetUnicodeString(I,
1873 ResultSet.GetUnicodeString(I));
1874 stBytes,stGUID: RowAccessor.SetBytes(I, ResultSet.GetBytes(I));
1875 stDate: RowAccessor.SetDate(I, ResultSet.GetDate(I));
1876 stTime: RowAccessor.SetTime(I, ResultSet.GetTime(I));
1877 stTimestamp: RowAccessor.SetTimestamp(I, ResultSet.GetTimestamp(I));
1878 stAsciiStream, stBinaryStream, stUnicodeStream:
1879 RowAccessor.SetBlob(I, ResultSet.GetBlob(I));
1880 stDataSet: RowAccessor.SetDataSet(i, ResultSet.GetDataSet(I));
1883 if ResultSet.WasNull then
1884 RowAccessor.SetNull(I);
1887 RowsList.Add(RowAccessor.RowBuffer);
1888 LastRowNo := RowsList.Count;
1890 RowAccessor.RowBuffer := TempRow;
1895 Fetches all of the rest rows from the wrapped result set.
1897 procedure TZCachedResultSet.FetchAll;
1903 Opens this recordset.
1905 procedure TZCachedResultSet.Open;
1908 ColumnInfo: TZColumnInfo;
1909 MetaData : IZResultSetMetaData;
1912 MetaData := FResultSet.GetMetadata;
1913 for I := 1 to Metadata.GetColumnCount do
1915 ColumnInfo := TZColumnInfo.Create;
1918 Currency := Metadata.IsCurrency(I);
1919 Signed := Metadata.IsSigned(I);
1920 ColumnDisplaySize := Metadata.GetColumnDisplaySize(I);
1921 ColumnLabel := Metadata.GetColumnLabel(I);
1922 Precision := Metadata.GetPrecision(I);
1923 Scale := Metadata.GetScale(I);
1924 ColumnType := Metadata.GetColumnType(I);
1926 ColumnsInfo.Add(ColumnInfo);
1933 Releases this <code>ResultSet</code> object's database and
1934 JDBC resources immediately instead of waiting for
1935 this to happen when it is automatically closed.
1937 <P><B>Note:</B> A <code>ResultSet</code> object
1938 is automatically closed by the
1939 <code>Statement</code> object that generated it when
1940 that <code>Statement</code> object is closed,
1941 re-executed, or is used to retrieve the next result from a
1942 sequence of multiple results. A <code>ResultSet</code> object
1943 is also automatically closed when it is garbage collected.
1945 procedure TZCachedResultSet.Close;
1949 If Assigned(FResultset) then
1955 Retrieves the number, types and properties of
1956 this <code>ResultSet</code> object's columns.
1957 @return the description of this <code>ResultSet</code> object's columns
1959 function TZCachedResultSet.GetMetadata: IZResultSetMetadata;
1961 Result := ResultSet.GetMetadata;
1965 Indicates whether the cursor is after the last row in
1966 this <code>ResultSet</code> object.
1968 @return <code>true</code> if the cursor is after the last row;
1969 <code>false</code> if the cursor is at any other position or the
1970 result set contains no rows
1972 function TZCachedResultSet.IsAfterLast: Boolean;
1975 Result := inherited IsAfterLast;
1979 Moves the cursor to the end of
1980 this <code>ResultSet</code> object, just after the
1981 last row. This method has no effect if the result set contains no rows.
1983 procedure TZCachedResultSet.AfterLast;
1986 inherited AfterLast;
1990 Indicates whether the cursor is on the last row of
1991 this <code>ResultSet</code> object.
1992 Note: Calling the method <code>isLast</code> may be expensive
1993 because the JDBC driver
1994 might need to fetch ahead one row in order to determine
1995 whether the current row is the last row in the result set.
1997 @return <code>true</code> if the cursor is on the last row;
1998 <code>false</code> otherwise
2000 function TZCachedResultSet.IsLast: Boolean;
2003 Result := inherited IsLast;
2007 Moves the cursor to the last row in
2008 this <code>ResultSet</code> object.
2010 @return <code>true</code> if the cursor is on a valid row;
2011 <code>false</code> if there are no rows in the result set
2013 function TZCachedResultSet.Last: Boolean;
2016 Result := inherited Last;
2020 Moves the cursor to the given row number in
2021 this <code>ResultSet</code> object.
2023 <p>If the row number is positive, the cursor moves to
2024 the given row number with respect to the
2025 beginning of the result set. The first row is row 1, the second
2026 is row 2, and so on.
2028 <p>If the given row number is negative, the cursor moves to
2029 an absolute row position with respect to
2030 the end of the result set. For example, calling the method
2031 <code>absolute(-1)</code> positions the
2032 cursor on the last row; calling the method <code>absolute(-2)</code>
2033 moves the cursor to the next-to-last row, and so on.
2035 <p>An attempt to position the cursor beyond the first/last row in
2036 the result set leaves the cursor before the first row or after
2039 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
2040 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
2041 is the same as calling <code>last()</code>.
2043 @return <code>true</code> if the cursor is on the result set;
2044 <code>false</code> otherwise
2046 function TZCachedResultSet.MoveAbsolute(Row: Integer): Boolean;
2048 { Checks for maximum row. }
2050 if (MaxRows > 0) and (Row > MaxRows) then
2053 { Processes negative rows }
2057 Row := LastRowNo - Row + 1;
2062 { Processes moving after last row }
2063 while (LastRowNo < Row) and Fetch do;
2065 Result := inherited MoveAbsolute(Row);