00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Caching Classes and Interfaces }
00005 { }
00006 { Originally written by Sergey Seroukhov }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZDbcCachedResultSet;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 {$IFNDEF VER130BELOW}
00062 Types,
00063 {$ENDIF}
00064 Classes, SysUtils, Contnrs, ZClasses, ZSysUtils, ZDbcIntfs, ZDbcResultSet,
00065 ZDbcCache, ZCompatibility;
00066
00067 type
00068
00069 IZCachedResultSet = interface;
00070
00071 {** Resolver to post updates. }
00072 IZCachedResolver = interface (IZInterface)
00073 ['{546ED716-BB88-468C-8CCE-D7111CF5E1EF}']
00074
00075 procedure CalculateDefaults(Sender: IZCachedResultSet;
00076 RowAccessor: TZRowAccessor);
00077 procedure PostUpdates(Sender: IZCachedResultSet; UpdateType: TZRowUpdateType;
00078 OldRowAccessor, NewRowAccessor: TZRowAccessor);
00079 {BEGIN of PATCH [1185969]: Do tasks after posting updates. ie: Updating AutoInc fields in MySQL }
00080 procedure UpdateAutoIncrementFields(Sender: IZCachedResultSet; UpdateType: TZRowUpdateType;
00081 OldRowAccessor, NewRowAccessor: TZRowAccessor; Resolver: IZCachedResolver);
00082 {END of PATCH [1185969]: Do tasks after posting updates. ie: Updating AutoInc fields in MySQL }
00083 end;
00084
00085 {** Represents a cached result set. }
00086 IZCachedResultSet = interface (IZResultSet)
00087 ['{BAF24A92-C8CE-4AB4-AEBC-3D4A9BCB0946}']
00088
00089 function GetResolver: IZCachedResolver;
00090 procedure SetResolver(Resolver: IZCachedResolver);
00091
00092 {BEGIN PATCH [1214009] Calc Defaults in TZUpdateSQL and Added Methods to GET and SET the database Native Resolver
00093 will help to implemented feature to Calculate default values in TZUpdateSQL
00094 comment: add this properties to get the original Resolver
00095 this will be useful whn using TZUpdateSQL
00096 }
00097 function GetNativeResolver: IZCachedResolver;
00098 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00099
00100 function IsCachedUpdates: Boolean;
00101 procedure SetCachedUpdates(Value: Boolean);
00102 function IsPendingUpdates: Boolean;
00103
00104 procedure PostUpdates;
00105 procedure CancelUpdates;
00106 procedure RevertRecord;
00107 procedure MoveToInitialRow;
00108 end;
00109
00110 {** Implements cached ResultSet. }
00111 TZAbstractCachedResultSet = class (TZAbstractResultSet, IZCachedResultSet)
00112 private
00113 FCachedUpdates: Boolean;
00114 FRowsList: TList;
00115 FInitialRowsList: TList;
00116 FCurrentRowsList: TList;
00117 FSelectedRow: PZRowBuffer;
00118 FUpdatedRow: PZRowBuffer;
00119 FInsertedRow: PZRowBuffer;
00120 FRowAccessor: TZRowAccessor;
00121 FNewRowAccessor: TZRowAccessor;
00122 FOldRowAccessor: TZRowAccessor;
00123 FNextRowIndex: Integer;
00124 FResolver: IZCachedResolver;
00125 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00126 FNativeResolver: IZCachedResolver;
00127 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00128 protected
00129 procedure CheckAvailable;
00130 procedure CheckUpdatable;
00131 procedure Open; override;
00132 function GetNextRowIndex: Integer;
00133
00134 procedure CalculateRowDefaults(RowAccessor: TZRowAccessor); virtual;
00135 procedure PostRowUpdates(OldRowAccessor,
00136 NewRowAccessor: TZRowAccessor); virtual;
00137 function LocateRow(RowsList: TList; RowIndex: Integer): Integer;
00138 function AppendRow(Row: PZRowBuffer): PZRowBuffer;
00139 procedure PrepareRowForUpdates;
00140
00141 property CachedUpdates: Boolean read FCachedUpdates write FCachedUpdates;
00142 property RowsList: TList read FRowsList write FRowsList;
00143 property InitialRowsList: TList read FInitialRowsList
00144 write FInitialRowsList;
00145 property CurrentRowsList: TList read FCurrentRowsList
00146 write FCurrentRowsList;
00147 property SelectedRow: PZRowBuffer read FSelectedRow write FSelectedRow;
00148 property UpdatedRow: PZRowBuffer read FUpdatedRow write FUpdatedRow;
00149 property InsertedRow: PZRowBuffer read FInsertedRow write FInsertedRow;
00150 property RowAccessor: TZRowAccessor read FRowAccessor write FRowAccessor;
00151 property OldRowAccessor: TZRowAccessor read FOldRowAccessor
00152 write FOldRowAccessor;
00153 property NewRowAccessor: TZRowAccessor read FNewRowAccessor
00154 write FNewRowAccessor;
00155 property NextRowIndex: Integer read FNextRowIndex write FNextRowIndex;
00156 property Resolver: IZCachedResolver read FResolver write FResolver;
00157 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00158 property NativeResolver: IZCachedResolver read FNativeResolver;
00159 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00160 public
00161 constructor CreateWithStatement(SQL: string; Statement: IZStatement);
00162 constructor CreateWithColumns(ColumnsInfo: TObjectList; SQL: string);
00163 destructor Destroy; override;
00164
00165 procedure Close; override;
00166
00167
00168
00169
00170
00171 function IsNull(ColumnIndex: Integer): Boolean; override;
00172 function GetPChar(ColumnIndex: Integer): PChar; override;
00173 function GetString(ColumnIndex: Integer): string; override;
00174 function GetUnicodeString(ColumnIndex: Integer): Widestring; override;
00175 function GetBoolean(ColumnIndex: Integer): Boolean; override;
00176 function GetByte(ColumnIndex: Integer): ShortInt; override;
00177 function GetShort(ColumnIndex: Integer): SmallInt; override;
00178 function GetInt(ColumnIndex: Integer): Integer; override;
00179 function GetLong(ColumnIndex: Integer): Int64; override;
00180 function GetFloat(ColumnIndex: Integer): Single; override;
00181 function GetDouble(ColumnIndex: Integer): Double; override;
00182 function GetBigDecimal(ColumnIndex: Integer): Extended; override;
00183 function GetBytes(ColumnIndex: Integer): TByteDynArray; override;
00184 function GetDate(ColumnIndex: Integer): TDateTime; override;
00185 function GetTime(ColumnIndex: Integer): TDateTime; override;
00186 function GetTimestamp(ColumnIndex: Integer): TDateTime; override;
00187 function GetBlob(ColumnIndex: Integer): IZBlob; override;
00188
00189
00190
00191
00192
00193 function MoveAbsolute(Row: Integer): Boolean; override;
00194
00195
00196
00197
00198
00199 function RowUpdated: Boolean; override;
00200 function RowInserted: Boolean; override;
00201 function RowDeleted: Boolean; override;
00202
00203 procedure UpdateNull(ColumnIndex: Integer); override;
00204 procedure UpdateBoolean(ColumnIndex: Integer; Value: Boolean); override;
00205 procedure UpdateByte(ColumnIndex: Integer; Value: ShortInt); override;
00206 procedure UpdateShort(ColumnIndex: Integer; Value: SmallInt); override;
00207 procedure UpdateInt(ColumnIndex: Integer; Value: Integer); override;
00208 procedure UpdateLong(ColumnIndex: Integer; Value: Int64); override;
00209 procedure UpdateFloat(ColumnIndex: Integer; Value: Single); override;
00210 procedure UpdateDouble(ColumnIndex: Integer; Value: Double); override;
00211 procedure UpdateBigDecimal(ColumnIndex: Integer; Value: Extended); override;
00212 procedure UpdatePChar(ColumnIndex: Integer; Value: PChar); override;
00213 procedure UpdateString(ColumnIndex: Integer; const Value: string); override;
00214 procedure UpdateUnicodeString(ColumnIndex: Integer; const Value: WideString); override;
00215 procedure UpdateBytes(ColumnIndex: Integer; const Value: TByteDynArray); override;
00216 procedure UpdateDate(ColumnIndex: Integer; Value: TDateTime); override;
00217 procedure UpdateTime(ColumnIndex: Integer; Value: TDateTime); override;
00218 procedure UpdateTimestamp(ColumnIndex: Integer; Value: TDateTime); override;
00219 procedure UpdateAsciiStream(ColumnIndex: Integer; Value: TStream); override;
00220 procedure UpdateUnicodeStream(ColumnIndex: Integer; Value: TStream); override;
00221 procedure UpdateBinaryStream(ColumnIndex: Integer; Value: TStream); override;
00222
00223 procedure InsertRow; override;
00224 procedure UpdateRow; override;
00225 procedure DeleteRow; override;
00226 procedure CancelRowUpdates; override;
00227 procedure MoveToInsertRow; override;
00228 procedure MoveToCurrentRow; override;
00229
00230 function CompareRows(Row1, Row2: Integer; const ColumnIndices: TIntegerDynArray;
00231 const ColumnDirs: TBooleanDynArray): Integer; override;
00232
00233
00234
00235
00236
00237 function GetResolver: IZCachedResolver;
00238 procedure SetResolver(Resolver: IZCachedResolver);
00239 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00240 function GetNativeResolver: IZCachedResolver;
00241 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00242 function IsCachedUpdates: Boolean;
00243 procedure SetCachedUpdates(Value: Boolean);
00244 function IsPendingUpdates: Boolean; virtual;
00245
00246 procedure PostUpdates; virtual;
00247 procedure CancelUpdates; virtual;
00248 procedure RevertRecord; virtual;
00249 procedure MoveToInitialRow; virtual;
00250 end;
00251
00252 {**
00253 Implements Abstract cached ResultSet. This class should be extended
00254 with database specific logic to form SQL data manipulation statements.
00255 }
00256 TZCachedResultSet = class(TZAbstractCachedResultSet)
00257 private
00258 FResultSet: IZResultSet;
00259 protected
00260 procedure Open; override;
00261 function Fetch: Boolean; virtual;
00262 procedure FetchAll; virtual;
00263
00264 property ResultSet: IZResultSet read FResultSet write FResultSet;
00265 public
00266 constructor Create(ResultSet: IZResultSet; SQL: string;
00267 Resolver: IZCachedResolver);
00268 destructor Destroy; override;
00269
00270 procedure Close; override;
00271 function GetMetaData: IZResultSetMetaData; override;
00272
00273 function IsAfterLast: Boolean; override;
00274 function IsLast: Boolean; override;
00275 procedure AfterLast; override;
00276 function Last: Boolean; override;
00277 function MoveAbsolute(Row: Integer): Boolean; override;
00278 end;
00279
00280 implementation
00281
00282 uses ZMessages, ZDbcResultSetMetadata, ZDbcGenericResolver, ZDbcUtils;
00283
00284 { TZAbstractCachedResultSet }
00285
00286 {**
00287 Creates this object and assignes the main properties.
00288 @param Statement an SQL statement object.
00289 @param SQL an SQL query.
00290 }
00291 constructor TZAbstractCachedResultSet.CreateWithStatement(SQL: string;
00292 Statement: IZStatement);
00293 begin
00294 inherited Create(Statement, SQL, nil);
00295 FCachedUpdates := False;
00296 end;
00297
00298 {**
00299 Creates this object and assignes the main properties.
00300 @param SQL an SQL query.
00301 @param ColumnsInfo a columns info for cached rows.
00302 }
00303 constructor TZAbstractCachedResultSet.CreateWithColumns(
00304 ColumnsInfo: TObjectList; SQL: string);
00305 begin
00306 inherited Create(nil, SQL, nil);
00307
00308 CopyColumnsInfo(ColumnsInfo, Self.ColumnsInfo);
00309 FCachedUpdates := False;
00310 Open;
00311 end;
00312
00313 {**
00314 Destroys this object and cleanups the memory.
00315 }
00316 destructor TZAbstractCachedResultSet.Destroy;
00317 begin
00318 FResolver := nil;
00319 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00320 FNativeResolver := nil;
00321 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00322 inherited Destroy;
00323 end;
00324
00325 {**
00326 Checks for availability of the cached buffer.
00327 }
00328 procedure TZAbstractCachedResultSet.CheckAvailable;
00329 begin
00330 CheckClosed;
00331 if (FRowAccessor = nil) or (FRowAccessor.RowBuffer = nil) then
00332 raise EZSQLException.Create(SRowDataIsNotAvailable);
00333 end;
00334
00335 {**
00336 Checks is the cached buffer updatable.
00337 }
00338 procedure TZAbstractCachedResultSet.CheckUpdatable;
00339 begin
00340 CheckAvailable;
00341 if ResultSetConcurrency <> rcUpdatable then
00342 RaiseReadOnlyException;
00343 end;
00344
00345 {**
00346 Generates the next row index value.
00347 @return the new generated row index.
00348 }
00349 function TZAbstractCachedResultSet.GetNextRowIndex: Integer;
00350 begin
00351 Result := FNextRowIndex;
00352 Inc(FNextRowIndex);
00353 end;
00354
00355 {**
00356 Finds a row with specified index among list of rows.
00357 @param RowsList a list of rows.
00358 @param Index a row index.
00359 @return a found row buffer of <code>null</code> otherwise.
00360 }
00361 function TZAbstractCachedResultSet.LocateRow(RowsList: TList;
00362 RowIndex: Integer): Integer;
00363 var
00364 I: Integer;
00365 begin
00366 Result := -1;
00367 for I := 0 to RowsList.Count - 1 do
00368 begin
00369 if PZRowBuffer(RowsList[I]).Index = RowIndex then
00370 begin
00371 Result := I;
00372 Break;
00373 end;
00374 end;
00375 end;
00376
00377 {**
00378 Appends a row to the list of rows if such row is not exist.
00379 @param Row a row buffer.
00380 @return an appended row buffer.
00381 }
00382 function TZAbstractCachedResultSet.AppendRow(Row: PZRowBuffer): PZRowBuffer;
00383 begin
00384 if LocateRow(FInitialRowsList, Row.Index) < 0 then
00385 begin
00386 FRowAccessor.AllocBuffer(Result);
00387 FRowAccessor.CopyBuffer(Row, Result);
00388 FInitialRowsList.Add(Result);
00389 FCurrentRowsList.Add(Row);
00390 end else
00391 Result := nil;
00392 end;
00393
00394 {**
00395 Prepares the current selected row for updates.
00396 }
00397 procedure TZAbstractCachedResultSet.PrepareRowForUpdates;
00398 begin
00399 if (RowAccessor.RowBuffer = FSelectedRow) and (FSelectedRow <> FUpdatedRow) then
00400 begin
00401 FSelectedRow := FUpdatedRow;
00402 RowAccessor.RowBuffer := FSelectedRow;
00403 RowAccessor.CloneFrom(PZRowBuffer(FRowsList[RowNo - 1]));
00404 end;
00405 end;
00406
00407 {**
00408 Calculates column default values..
00409 @param RowAccessor a row accessor which contains new column values.
00410 }
00411 procedure TZAbstractCachedResultSet.CalculateRowDefaults(
00412 RowAccessor: TZRowAccessor);
00413 begin
00414 {$IFNDEF DISABLE_CHECKING}
00415 if Resolver = nil then
00416 raise EZSQLException.Create(SResolverIsNotSpecified);
00417 {$ENDIF}
00418 Resolver.CalculateDefaults(Self, RowAccessor);
00419 end;
00420
00421 {**
00422 Post changes to database server.
00423 @param OldRowAccessor a row accessor which contains old column values.
00424 @param NewRowAccessor a row accessor which contains new or updated
00425 column values.
00426 }
00427 procedure TZAbstractCachedResultSet.PostRowUpdates(OldRowAccessor,
00428 NewRowAccessor: TZRowAccessor);
00429 begin
00430 {$IFNDEF DISABLE_CHECKING}
00431 if Resolver = nil then
00432 raise EZSQLException.Create(SResolverIsNotSpecified);
00433 {$ENDIF}
00434 Resolver.PostUpdates(Self, NewRowAccessor.RowBuffer.UpdateType,
00435 OldRowAccessor, NewRowAccessor);
00436 end;
00437
00438 {**
00439 Gets a cached updates resolver object.
00440 @return a cached updates resolver object.
00441 }
00442 function TZAbstractCachedResultSet.GetResolver: IZCachedResolver;
00443 begin
00444 Result := FResolver;
00445 end;
00446
00447 {**
00448 Sets a new cached updates resolver object.
00449 @param Resolver a cached updates resolver object.
00450 }
00451 procedure TZAbstractCachedResultSet.SetResolver(Resolver: IZCachedResolver);
00452 begin
00453 FResolver := Resolver;
00454 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00455 if FNativeResolver = nil then
00456 FNativeResolver := Resolver;
00457 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00458 end;
00459 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00460 {**
00461 Gets a Native cached updates resolver object.
00462 @return a Native cached updates resolver object.
00463 }
00464 function TZAbstractCachedResultSet.GetNativeResolver: IZCachedResolver;
00465 begin
00466 Result := FNativeResolver;
00467 end;
00468 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
00469
00470 {**
00471 Checks is the cached updates mode turned on.
00472 @return <code>True</code> if the cached updates mode turned on.
00473 }
00474 function TZAbstractCachedResultSet.IsCachedUpdates: Boolean;
00475 begin
00476 Result := FCachedUpdates;
00477 end;
00478
00479 {**
00480 Switched the cached updates mode.
00481 @param Value boolean flag which turns on/off the cached updates mode.
00482 }
00483 procedure TZAbstractCachedResultSet.SetCachedUpdates(Value: Boolean);
00484 begin
00485 if FCachedUpdates <> Value then
00486 begin
00487 FCachedUpdates := Value;
00488 if not FCachedUpdates then
00489 PostUpdates;
00490 end;
00491 end;
00492
00493 {**
00494 Checks is cached updates pending.
00495 @return <code>True</code> if the cached updates pending.
00496 }
00497 function TZAbstractCachedResultSet.IsPendingUpdates: Boolean;
00498 begin
00499 Result := FInitialRowsList.Count > 0;
00500 end;
00501
00502 {**
00503 Moves to the current row with initial column values.
00504 }
00505 procedure TZAbstractCachedResultSet.MoveToInitialRow;
00506 var
00507 Index: Integer;
00508 begin
00509 CheckClosed;
00510 if (RowNo >= 1) and (RowNo <= LastRowNo) and (FSelectedRow <> nil) then
00511 begin
00512 Index := LocateRow(FInitialRowsList, FSelectedRow.Index);
00513 if Index >= 0 then
00514 begin
00515 FSelectedRow := FInitialRowsList[Index];
00516 FRowAccessor.RowBuffer := FSelectedRow;
00517 end;
00518 end else
00519 FRowAccessor.RowBuffer := nil;
00520 end;
00521
00522 {**
00523 Posts all saved updates to the server.
00524 }
00525 procedure TZAbstractCachedResultSet.PostUpdates;
00526 begin
00527 CheckClosed;
00528 if FInitialRowsList.Count > 0 then
00529 begin
00530 while FInitialRowsList.Count > 0 do
00531 begin
00532 OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[0]);
00533 NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[0]);
00534
00535 { Updates default field values. }
00536 if NewRowAccessor.RowBuffer.UpdateType = utInserted then
00537 CalculateRowDefaults(NewRowAccessor);
00538
00539 { Posts row updates and processes the exceptions. }
00540 PostRowUpdates(OldRowAccessor, NewRowAccessor);
00541
00542 { If post was Ok - update the row update type. }
00543 if NewRowAccessor.RowBuffer.UpdateType <> utDeleted then
00544 begin
00545 NewRowAccessor.RowBuffer.UpdateType := utUnmodified;
00546 if (FSelectedRow <> nil)
00547 and (FSelectedRow.Index = NewRowAccessor.RowBuffer.Index) then
00548 FSelectedRow.UpdateType := utUnmodified;
00549 end;
00550
00551 { Removes cached rows. }
00552 OldRowAccessor.Dispose;
00553 FInitialRowsList.Delete(0);
00554 FCurrentRowsList.Delete(0);
00555 end;
00556 end;
00557 end;
00558
00559 {**
00560 Cancels updates for all rows.
00561 }
00562 procedure TZAbstractCachedResultSet.CancelUpdates;
00563 var
00564 InitialRow, CurrentRow: PZRowBuffer;
00565 begin
00566 CheckClosed;
00567 while FInitialRowsList.Count > 0 do
00568 begin
00569 InitialRow := PZRowBuffer(FInitialRowsList[0]);
00570 CurrentRow := PZRowBuffer(FCurrentRowsList[0]);
00571
00572 if CurrentRow.UpdateType = utInserted then
00573 InitialRow.UpdateType := utDeleted;
00574
00575 FRowAccessor.CopyBuffer(InitialRow, CurrentRow);
00576 if (FSelectedRow = FUpdatedRow)
00577 and (FSelectedRow.Index = InitialRow.Index) then
00578 FRowAccessor.CopyBuffer(InitialRow, FSelectedRow);
00579
00580 FRowAccessor.DisposeBuffer(InitialRow);
00581 FInitialRowsList.Delete(0);
00582 FCurrentRowsList.Delete(0);
00583 end;
00584 end;
00585
00586 {**
00587 Cancels updates for the current row.
00588 }
00589 procedure TZAbstractCachedResultSet.RevertRecord;
00590 var
00591 Index: Integer;
00592 InitialRow, CurrentRow: PZRowBuffer;
00593 begin
00594 CheckClosed;
00595 if (RowNo >= 1) and (RowNo <= LastRowNo) then
00596 begin
00597 Index := LocateRow(FInitialRowsList, FSelectedRow.Index);
00598 if Index >= 0 then
00599 begin
00600 InitialRow := PZRowBuffer(FInitialRowsList[Index]);
00601 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
00602
00603 if CurrentRow.UpdateType = utInserted then
00604 InitialRow.UpdateType := utDeleted;
00605 FRowAccessor.CopyBuffer(InitialRow, CurrentRow);
00606 if (FSelectedRow = FUpdatedRow) then
00607 FRowAccessor.CopyBuffer(InitialRow, FSelectedRow);
00608
00609 FRowAccessor.DisposeBuffer(InitialRow);
00610 FInitialRowsList.Delete(Index);
00611 FCurrentRowsList.Delete(Index);
00612 end;
00613 end;
00614 end;
00615
00616 {**
00617 Opens this recordset.
00618 }
00619 procedure TZAbstractCachedResultSet.Open;
00620 begin
00621 if not Closed then
00622 raise EZSQLException.Create(SResultsetIsAlreadyOpened);
00623
00624 FRowsList := TList.Create;
00625 FInitialRowsList := TList.Create;
00626 FCurrentRowsList := TList.Create;
00627
00628 FRowAccessor := TZRowAccessor.Create(ColumnsInfo);
00629 FOldRowAccessor := TZRowAccessor.Create(ColumnsInfo);
00630 FNewRowAccessor := TZRowAccessor.Create(ColumnsInfo);
00631
00632 FRowAccessor.AllocBuffer(FUpdatedRow);
00633 FRowAccessor.AllocBuffer(FInsertedRow);
00634 FSelectedRow := nil;
00635
00636 FNextRowIndex := 0;
00637
00638 if (Resolver = nil) and (GetConcurrency = rcUpdatable) then
00639 Resolver := TZGenericCachedResolver.Create(GetStatement, GetMetadata);
00640
00641 inherited Open;
00642 end;
00643
00644 {**
00645 Releases this <code>ResultSet</code> object's database and
00646 JDBC resources immediately instead of waiting for
00647 this to happen when it is automatically closed.
00648
00649 <P><B>Note:</B> A <code>ResultSet</code> object
00650 is automatically closed by the
00651 <code>Statement</code> object that generated it when
00652 that <code>Statement</code> object is closed,
00653 re-executed, or is used to retrieve the next result from a
00654 sequence of multiple results. A <code>ResultSet</code> object
00655 is also automatically closed when it is garbage collected.
00656 }
00657 procedure TZAbstractCachedResultSet.Close;
00658 var
00659 I: Integer;
00660 begin
00661 inherited Close;
00662
00663 if Assigned(FRowAccessor) then
00664 begin
00665 for I := 0 to FRowsList.Count - 1 do
00666 FRowAccessor.DisposeBuffer(PZRowBuffer(FRowsList[I]));
00667 for I := 0 to FInitialRowsList.Count - 1 do
00668 FRowAccessor.DisposeBuffer(PZRowBuffer(FInitialRowsList[I]));
00669
00670 FRowAccessor.DisposeBuffer(FUpdatedRow);
00671 FUpdatedRow := nil;
00672 FRowAccessor.DisposeBuffer(FInsertedRow);
00673 FInsertedRow := nil;
00674 FSelectedRow := nil;
00675
00676 FRowsList.Free;
00677 FRowsList := nil;
00678 FInitialRowsList.Free;
00679 FInitialRowsList := nil;
00680 FCurrentRowsList.Free;
00681 FCurrentRowsList := nil;
00682
00683 FRowAccessor.Free;
00684 FRowAccessor := nil;
00685 FOldRowAccessor.Free;
00686 FOldRowAccessor := nil;
00687 FNewRowAccessor.Free;
00688 FNewRowAccessor := nil;
00689 end;
00690 end;
00691
00692 //======================================================================
00693 // Methods for accessing results by column index
00694 //======================================================================
00695
00696 {**
00697 Indicates if the value of the designated column in the current row
00698 of this <code>ResultSet</code> object is Null.
00699
00700 @param columnIndex the first column is 1, the second is 2, ...
00701 @return if the value is SQL <code>NULL</code>, the
00702 value returned is <code>true</code>. <code>false</code> otherwise.
00703 }
00704 function TZAbstractCachedResultSet.IsNull(ColumnIndex: Integer): Boolean;
00705 begin
00706 {$IFNDEF DISABLE_CHECKING}
00707 CheckAvailable;
00708 {$ENDIF}
00709 Result := FRowAccessor.IsNull(ColumnIndex);
00710 end;
00711
00712 {**
00713 Gets the value of the designated column in the current row
00714 of this <code>ResultSet</code> object as
00715 a <code>PChar</code> in the Delphi programming language.
00716
00717 @param columnIndex the first column is 1, the second is 2, ...
00718 @return the column value; if the value is SQL <code>NULL</code>, the
00719 value returned is <code>null</code>
00720 }
00721 function TZAbstractCachedResultSet.GetPChar(ColumnIndex: Integer): PChar;
00722 begin
00723 {$IFNDEF DISABLE_CHECKING}
00724 CheckAvailable;
00725 {$ENDIF}
00726 Result := FRowAccessor.GetPChar(ColumnIndex, LastWasNull);
00727 end;
00728
00729 {**
00730 Gets the value of the designated column in the current row
00731 of this <code>ResultSet</code> object as
00732 a <code>String</code> in the Java programming language.
00733
00734 @param columnIndex the first column is 1, the second is 2, ...
00735 @return the column value; if the value is SQL <code>NULL</code>, the
00736 value returned is <code>null</code>
00737 }
00738 function TZAbstractCachedResultSet.GetString(ColumnIndex: Integer): string;
00739 begin
00740 {$IFNDEF DISABLE_CHECKING}
00741 CheckAvailable;
00742 {$ENDIF}
00743 Result := FRowAccessor.GetString(ColumnIndex, LastWasNull);
00744 end;
00745
00746 {**
00747 Gets the value of the designated column in the current row
00748 of this <code>ResultSet</code> object as
00749 a <code>Widestring</code> in the Java programming language.
00750
00751 @param columnIndex the first column is 1, the second is 2, ...
00752 @return the column value; if the value is SQL <code>NULL</code>, the
00753 value returned is <code>null</code>
00754 }
00755 function TZAbstractCachedResultSet.GetUnicodeString(ColumnIndex: Integer): Widestring;
00756 begin
00757 {$IFNDEF DISABLE_CHECKING}
00758 CheckAvailable;
00759 {$ENDIF}
00760 Result := FRowAccessor.GetUnicodeString(ColumnIndex, LastWasNull);
00761 end;
00762
00763 {**
00764 Gets the value of the designated column in the current row
00765 of this <code>ResultSet</code> object as
00766 a <code>boolean</code> in the Java programming language.
00767
00768 @param columnIndex the first column is 1, the second is 2, ...
00769 @return the column value; if the value is SQL <code>NULL</code>, the
00770 value returned is <code>false</code>
00771 }
00772 function TZAbstractCachedResultSet.GetBoolean(ColumnIndex: Integer): Boolean;
00773 begin
00774 {$IFNDEF DISABLE_CHECKING}
00775 CheckAvailable;
00776 {$ENDIF}
00777 Result := FRowAccessor.GetBoolean(ColumnIndex, LastWasNull);
00778 end;
00779
00780 {**
00781 Gets the value of the designated column in the current row
00782 of this <code>ResultSet</code> object as
00783 a <code>byte</code> in the Java programming language.
00784
00785 @param columnIndex the first column is 1, the second is 2, ...
00786 @return the column value; if the value is SQL <code>NULL</code>, the
00787 value returned is <code>0</code>
00788 }
00789 function TZAbstractCachedResultSet.GetByte(ColumnIndex: Integer): ShortInt;
00790 begin
00791 {$IFNDEF DISABLE_CHECKING}
00792 CheckAvailable;
00793 {$ENDIF}
00794 Result := FRowAccessor.GetByte(ColumnIndex, LastWasNull);
00795 end;
00796
00797 {**
00798 Gets the value of the designated column in the current row
00799 of this <code>ResultSet</code> object as
00800 a <code>short</code> in the Java programming language.
00801
00802 @param columnIndex the first column is 1, the second is 2, ...
00803 @return the column value; if the value is SQL <code>NULL</code>, the
00804 value returned is <code>0</code>
00805 }
00806 function TZAbstractCachedResultSet.GetShort(ColumnIndex: Integer): SmallInt;
00807 begin
00808 {$IFNDEF DISABLE_CHECKING}
00809 CheckAvailable;
00810 {$ENDIF}
00811 Result := FRowAccessor.GetShort(ColumnIndex, LastWasNull);
00812 end;
00813
00814 {**
00815 Gets the value of the designated column in the current row
00816 of this <code>ResultSet</code> object as
00817 an <code>int</code> in the Java programming language.
00818
00819 @param columnIndex the first column is 1, the second is 2, ...
00820 @return the column value; if the value is SQL <code>NULL</code>, the
00821 value returned is <code>0</code>
00822 }
00823 function TZAbstractCachedResultSet.GetInt(ColumnIndex: Integer): Integer;
00824 begin
00825 {$IFNDEF DISABLE_CHECKING}
00826 CheckAvailable;
00827 {$ENDIF}
00828 Result := FRowAccessor.GetInt(ColumnIndex, LastWasNull);
00829 end;
00830
00831 {**
00832 Gets the value of the designated column in the current row
00833 of this <code>ResultSet</code> object as
00834 a <code>long</code> in the Java programming language.
00835
00836 @param columnIndex the first column is 1, the second is 2, ...
00837 @return the column value; if the value is SQL <code>NULL</code>, the
00838 value returned is <code>0</code>
00839 }
00840 function TZAbstractCachedResultSet.GetLong(ColumnIndex: Integer): Int64;
00841 begin
00842 {$IFNDEF DISABLE_CHECKING}
00843 CheckAvailable;
00844 {$ENDIF}
00845 Result := FRowAccessor.GetLong(ColumnIndex, LastWasNull);
00846 end;
00847
00848 {**
00849 Gets the value of the designated column in the current row
00850 of this <code>ResultSet</code> object as
00851 a <code>float</code> in the Java programming language.
00852
00853 @param columnIndex the first column is 1, the second is 2, ...
00854 @return the column value; if the value is SQL <code>NULL</code>, the
00855 value returned is <code>0</code>
00856 }
00857 function TZAbstractCachedResultSet.GetFloat(ColumnIndex: Integer): Single;
00858 begin
00859 {$IFNDEF DISABLE_CHECKING}
00860 CheckAvailable;
00861 {$ENDIF}
00862 Result := FRowAccessor.GetFloat(ColumnIndex, LastWasNull);
00863 end;
00864
00865 {**
00866 Gets the value of the designated column in the current row
00867 of this <code>ResultSet</code> object as
00868 a <code>double</code> in the Java programming language.
00869
00870 @param columnIndex the first column is 1, the second is 2, ...
00871 @return the column value; if the value is SQL <code>NULL</code>, the
00872 value returned is <code>0</code>
00873 }
00874 function TZAbstractCachedResultSet.GetDouble(ColumnIndex: Integer): Double;
00875 begin
00876 {$IFNDEF DISABLE_CHECKING}
00877 CheckAvailable;
00878 {$ENDIF}
00879 Result := FRowAccessor.GetDouble(ColumnIndex, LastWasNull);
00880 end;
00881
00882 {**
00883 Gets the value of the designated column in the current row
00884 of this <code>ResultSet</code> object as
00885 a <code>java.sql.BigDecimal</code> in the Java programming language.
00886
00887 @param columnIndex the first column is 1, the second is 2, ...
00888 @param scale the number of digits to the right of the decimal point
00889 @return the column value; if the value is SQL <code>NULL</code>, the
00890 value returned is <code>null</code>
00891 }
00892 function TZAbstractCachedResultSet.GetBigDecimal(ColumnIndex: Integer): Extended;
00893 begin
00894 {$IFNDEF DISABLE_CHECKING}
00895 CheckAvailable;
00896 {$ENDIF}
00897 Result := FRowAccessor.GetBigDecimal(ColumnIndex, LastWasNull);
00898 end;
00899
00900 {**
00901 Gets the value of the designated column in the current row
00902 of this <code>ResultSet</code> object as
00903 a <code>byte</code> array in the Java programming language.
00904 The bytes represent the raw values returned by the driver.
00905
00906 @param columnIndex the first column is 1, the second is 2, ...
00907 @return the column value; if the value is SQL <code>NULL</code>, the
00908 value returned is <code>null</code>
00909 }
00910 function TZAbstractCachedResultSet.GetBytes(ColumnIndex: Integer): TByteDynArray;
00911 begin
00912 {$IFNDEF DISABLE_CHECKING}
00913 CheckAvailable;
00914 {$ENDIF}
00915 Result := FRowAccessor.GetBytes(ColumnIndex, LastWasNull);
00916 end;
00917
00918 {**
00919 Gets the value of the designated column in the current row
00920 of this <code>ResultSet</code> object as
00921 a <code>java.sql.Date</code> object in the Java programming language.
00922
00923 @param columnIndex the first column is 1, the second is 2, ...
00924 @return the column value; if the value is SQL <code>NULL</code>, the
00925 value returned is <code>null</code>
00926 }
00927 function TZAbstractCachedResultSet.GetDate(ColumnIndex: Integer): TDateTime;
00928 begin
00929 {$IFNDEF DISABLE_CHECKING}
00930 CheckAvailable;
00931 {$ENDIF}
00932 Result := FRowAccessor.GetDate(ColumnIndex, LastWasNull);
00933 end;
00934
00935 {**
00936 Gets the value of the designated column in the current row
00937 of this <code>ResultSet</code> object as
00938 a <code>java.sql.Time</code> object in the Java programming language.
00939
00940 @param columnIndex the first column is 1, the second is 2, ...
00941 @return the column value; if the value is SQL <code>NULL</code>, the
00942 value returned is <code>null</code>
00943 }
00944 function TZAbstractCachedResultSet.GetTime(ColumnIndex: Integer): TDateTime;
00945 begin
00946 {$IFNDEF DISABLE_CHECKING}
00947 CheckAvailable;
00948 {$ENDIF}
00949 Result := FRowAccessor.GetTime(ColumnIndex, LastWasNull);
00950 end;
00951
00952 {**
00953 Gets the value of the designated column in the current row
00954 of this <code>ResultSet</code> object as
00955 a <code>java.sql.Timestamp</code> object in the Java programming language.
00956
00957 @param columnIndex the first column is 1, the second is 2, ...
00958 @return the column value; if the value is SQL <code>NULL</code>, the
00959 value returned is <code>null</code>
00960 @exception SQLException if a database access error occurs
00961 }
00962 function TZAbstractCachedResultSet.GetTimestamp(ColumnIndex: Integer): TDateTime;
00963 begin
00964 {$IFNDEF DISABLE_CHECKING}
00965 CheckAvailable;
00966 {$ENDIF}
00967 Result := FRowAccessor.GetTimestamp(ColumnIndex, LastWasNull);
00968 end;
00969
00970 {**
00971 Returns the value of the designated column in the current row
00972 of this <code>ResultSet</code> object as a <code>Blob</code> object
00973 in the Java programming language.
00974
00975 @param ColumnIndex the first column is 1, the second is 2, ...
00976 @return a <code>Blob</code> object representing the SQL <code>BLOB</code> value in
00977 the specified column
00978 }
00979 function TZAbstractCachedResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
00980 begin
00981 {$IFNDEF DISABLE_CHECKING}
00982 CheckAvailable;
00983 {$ENDIF}
00984 Result := FRowAccessor.GetBlob(ColumnIndex, LastWasNull);
00985 end;
00986
00987 //---------------------------------------------------------------------
00988 // Updates
00989 //---------------------------------------------------------------------
00990
00991 {**
00992 Gives a nullable column a null value.
00993
00994 The <code>updateXXX</code> methods are used to update column values in the
00995 current row or the insert row. The <code>updateXXX</code> methods do not
00996 update the underlying database; instead the <code>updateRow</code>
00997 or <code>insertRow</code> methods are called to update the database.
00998
00999 @param columnIndex the first column is 1, the second is 2, ...
01000 }
01001 procedure TZAbstractCachedResultSet.UpdateNull(ColumnIndex: Integer);
01002 begin
01003 {$IFNDEF DISABLE_CHECKING}
01004 CheckUpdatable;
01005 {$ENDIF}
01006 PrepareRowForUpdates;
01007 FRowAccessor.SetNull(ColumnIndex);
01008 end;
01009
01010 {**
01011 Updates the designated column with a <code>boolean</code> value.
01012 The <code>updateXXX</code> methods are used to update column values in the
01013 current row or the insert row. The <code>updateXXX</code> methods do not
01014 update the underlying database; instead the <code>updateRow</code> or
01015 <code>insertRow</code> methods are called to update the database.
01016
01017 @param columnIndex the first column is 1, the second is 2, ...
01018 @param x the new column value
01019 }
01020 procedure TZAbstractCachedResultSet.UpdateBoolean(ColumnIndex: Integer;
01021 Value: Boolean);
01022 begin
01023 {$IFNDEF DISABLE_CHECKING}
01024 CheckUpdatable;
01025 {$ENDIF}
01026 PrepareRowForUpdates;
01027 FRowAccessor.SetBoolean(ColumnIndex, Value);
01028 end;
01029
01030 {**
01031 Updates the designated column with a <code>byte</code> value.
01032 The <code>updateXXX</code> methods are used to update column values in the
01033 current row or the insert row. The <code>updateXXX</code> methods do not
01034 update the underlying database; instead the <code>updateRow</code> or
01035 <code>insertRow</code> methods are called to update the database.
01036
01037 @param columnIndex the first column is 1, the second is 2, ...
01038 @param x the new column value
01039 }
01040 procedure TZAbstractCachedResultSet.UpdateByte(ColumnIndex: Integer;
01041 Value: ShortInt);
01042 begin
01043 {$IFNDEF DISABLE_CHECKING}
01044 CheckUpdatable;
01045 {$ENDIF}
01046 PrepareRowForUpdates;
01047 FRowAccessor.SetByte(ColumnIndex, Value);
01048 end;
01049
01050 {**
01051 Updates the designated column with a <code>short</code> value.
01052 The <code>updateXXX</code> methods are used to update column values in the
01053 current row or the insert row. The <code>updateXXX</code> methods do not
01054 update the underlying database; instead the <code>updateRow</code> or
01055 <code>insertRow</code> methods are called to update the database.
01056
01057 @param columnIndex the first column is 1, the second is 2, ...
01058 @param x the new column value
01059 }
01060 procedure TZAbstractCachedResultSet.UpdateShort(ColumnIndex: Integer;
01061 Value: SmallInt);
01062 begin
01063 {$IFNDEF DISABLE_CHECKING}
01064 CheckUpdatable;
01065 {$ENDIF}
01066 PrepareRowForUpdates;
01067 FRowAccessor.SetShort(ColumnIndex, Value);
01068 end;
01069
01070 {**
01071 Updates the designated column with an <code>int</code> value.
01072 The <code>updateXXX</code> methods are used to update column values in the
01073 current row or the insert row. The <code>updateXXX</code> methods do not
01074 update the underlying database; instead the <code>updateRow</code> or
01075 <code>insertRow</code> methods are called to update the database.
01076
01077 @param columnIndex the first column is 1, the second is 2, ...
01078 @param x the new column value
01079 }
01080 procedure TZAbstractCachedResultSet.UpdateInt(ColumnIndex, Value: Integer);
01081 begin
01082 {$IFNDEF DISABLE_CHECKING}
01083 CheckUpdatable;
01084 {$ENDIF}
01085 PrepareRowForUpdates;
01086 FRowAccessor.SetInt(ColumnIndex, Value);
01087 end;
01088
01089 {**
01090 Updates the designated column with a <code>long</code> value.
01091 The <code>updateXXX</code> methods are used to update column values in the
01092 current row or the insert row. The <code>updateXXX</code> methods do not
01093 update the underlying database; instead the <code>updateRow</code> or
01094 <code>insertRow</code> methods are called to update the database.
01095
01096 @param columnIndex the first column is 1, the second is 2, ...
01097 @param x the new column value
01098 }
01099 procedure TZAbstractCachedResultSet.UpdateLong(ColumnIndex: Integer;
01100 Value: Int64);
01101 begin
01102 {$IFNDEF DISABLE_CHECKING}
01103 CheckUpdatable;
01104 {$ENDIF}
01105 PrepareRowForUpdates;
01106 FRowAccessor.SetLong(ColumnIndex, Value);
01107 end;
01108
01109 {**
01110 Updates the designated column with a <code>float</code> value.
01111 The <code>updateXXX</code> methods are used to update column values in the
01112 current row or the insert row. The <code>updateXXX</code> methods do not
01113 update the underlying database; instead the <code>updateRow</code> or
01114 <code>insertRow</code> methods are called to update the database.
01115
01116 @param columnIndex the first column is 1, the second is 2, ...
01117 @param x the new column value
01118 }
01119 procedure TZAbstractCachedResultSet.UpdateFloat(ColumnIndex: Integer;
01120 Value: Single);
01121 begin
01122 {$IFNDEF DISABLE_CHECKING}
01123 CheckUpdatable;
01124 {$ENDIF}
01125 PrepareRowForUpdates;
01126 FRowAccessor.SetFloat(ColumnIndex, Value);
01127 end;
01128
01129 {**
01130 Updates the designated column with a <code>double</code> value.
01131 The <code>updateXXX</code> methods are used to update column values in the
01132 current row or the insert row. The <code>updateXXX</code> methods do not
01133 update the underlying database; instead the <code>updateRow</code> or
01134 <code>insertRow</code> methods are called to update the database.
01135
01136 @param columnIndex the first column is 1, the second is 2, ...
01137 @param x the new column value
01138 }
01139 procedure TZAbstractCachedResultSet.UpdateDouble(ColumnIndex: Integer;
01140 Value: Double);
01141 begin
01142 {$IFNDEF DISABLE_CHECKING}
01143 CheckUpdatable;
01144 {$ENDIF}
01145 PrepareRowForUpdates;
01146 FRowAccessor.SetDouble(ColumnIndex, Value);
01147 end;
01148
01149 {**
01150 Updates the designated column with a <code>java.math.BigDecimal</code>
01151 value.
01152 The <code>updateXXX</code> methods are used to update column values in the
01153 current row or the insert row. The <code>updateXXX</code> methods do not
01154 update the underlying database; instead the <code>updateRow</code> or
01155 <code>insertRow</code> methods are called to update the database.
01156
01157 @param columnIndex the first column is 1, the second is 2, ...
01158 @param x the new column value
01159 }
01160 procedure TZAbstractCachedResultSet.UpdateBigDecimal(ColumnIndex: Integer;
01161 Value: Extended);
01162 begin
01163 {$IFNDEF DISABLE_CHECKING}
01164 CheckUpdatable;
01165 {$ENDIF}
01166 PrepareRowForUpdates;
01167 FRowAccessor.SetBigDecimal(ColumnIndex, Value);
01168 end;
01169
01170 {**
01171 Updates the designated column with a <code>String</code> value.
01172 The <code>updateXXX</code> methods are used to update column values in the
01173 current row or the insert row. The <code>updateXXX</code> methods do not
01174 update the underlying database; instead the <code>updateRow</code> or
01175 <code>insertRow</code> methods are called to update the database.
01176
01177 @param columnIndex the first column is 1, the second is 2, ...
01178 @param x the new column value
01179 }
01180 procedure TZAbstractCachedResultSet.UpdatePChar(ColumnIndex: Integer;
01181 Value: PChar);
01182 begin
01183 {$IFNDEF DISABLE_CHECKING}
01184 CheckUpdatable;
01185 {$ENDIF}
01186 PrepareRowForUpdates;
01187 FRowAccessor.SetPChar(ColumnIndex, Value);
01188 end;
01189
01190 {**
01191 Updates the designated column with a <code>String</code> value.
01192 The <code>updateXXX</code> methods are used to update column values in the
01193 current row or the insert row. The <code>updateXXX</code> methods do not
01194 update the underlying database; instead the <code>updateRow</code> or
01195 <code>insertRow</code> methods are called to update the database.
01196
01197 @param columnIndex the first column is 1, the second is 2, ...
01198 @param x the new column value
01199 }
01200 procedure TZAbstractCachedResultSet.UpdateString(ColumnIndex: Integer;
01201 const Value: string);
01202 begin
01203 {$IFNDEF DISABLE_CHECKING}
01204 CheckUpdatable;
01205 {$ENDIF}
01206 PrepareRowForUpdates;
01207 FRowAccessor.SetString(ColumnIndex, Value);
01208 end;
01209
01210 {**
01211 Updates the designated column with a <code>Widestring</code> value.
01212 The <code>updateXXX</code> methods are used to update column values in the
01213 current row or the insert row. The <code>updateXXX</code> methods do not
01214 update the underlying database; instead the <code>updateRow</code> or
01215 <code>insertRow</code> methods are called to update the database.
01216
01217 @param columnIndex the first column is 1, the second is 2, ...
01218 @param x the new column value
01219 }
01220 procedure TZAbstractCachedResultSet.UpdateUnicodeString(ColumnIndex: Integer;
01221 const Value: WideString);
01222 begin
01223 {$IFNDEF DISABLE_CHECKING}
01224 CheckUpdatable;
01225 {$ENDIF}
01226 PrepareRowForUpdates;
01227 FRowAccessor.SetUnicodeString(ColumnIndex, Value);
01228 end;
01229
01230 {**
01231 Updates the designated column with a <code>byte</code> array value.
01232 The <code>updateXXX</code> methods are used to update column values in the
01233 current row or the insert row. The <code>updateXXX</code> methods do not
01234 update the underlying database; instead the <code>updateRow</code> or
01235 <code>insertRow</code> methods are called to update the database.
01236
01237 @param columnIndex the first column is 1, the second is 2, ...
01238 @param x the new column value
01239 }
01240 procedure TZAbstractCachedResultSet.UpdateBytes(ColumnIndex: Integer;
01241 const Value: TByteDynArray);
01242 begin
01243 {$IFNDEF DISABLE_CHECKING}
01244 CheckUpdatable;
01245 {$ENDIF}
01246 PrepareRowForUpdates;
01247 FRowAccessor.SetBytes(ColumnIndex, Value);
01248 end;
01249
01250 {**
01251 Updates the designated column with a <code>java.sql.Date</code> value.
01252 The <code>updateXXX</code> methods are used to update column values in the
01253 current row or the insert row. The <code>updateXXX</code> methods do not
01254 update the underlying database; instead the <code>updateRow</code> or
01255 <code>insertRow</code> methods are called to update the database.
01256
01257 @param columnIndex the first column is 1, the second is 2, ...
01258 @param x the new column value
01259 }
01260 procedure TZAbstractCachedResultSet.UpdateDate(ColumnIndex: Integer;
01261 Value: TDateTime);
01262 begin
01263 {$IFNDEF DISABLE_CHECKING}
01264 CheckUpdatable;
01265 {$ENDIF}
01266 PrepareRowForUpdates;
01267 FRowAccessor.SetDate(ColumnIndex, Value);
01268 end;
01269
01270 {**
01271 Updates the designated column with a <code>java.sql.Time</code> value.
01272 The <code>updateXXX</code> methods are used to update column values in the
01273 current row or the insert row. The <code>updateXXX</code> methods do not
01274 update the underlying database; instead the <code>updateRow</code> or
01275 <code>insertRow</code> methods are called to update the database.
01276
01277 @param columnIndex the first column is 1, the second is 2, ...
01278 @param x the new column value
01279 }
01280 procedure TZAbstractCachedResultSet.UpdateTime(ColumnIndex: Integer;
01281 Value: TDateTime);
01282 begin
01283 {$IFNDEF DISABLE_CHECKING}
01284 CheckUpdatable;
01285 {$ENDIF}
01286 PrepareRowForUpdates;
01287 FRowAccessor.SetTime(ColumnIndex, Value);
01288 end;
01289
01290 {**
01291 Updates the designated column with a <code>java.sql.Timestamp</code>
01292 value.
01293 The <code>updateXXX</code> methods are used to update column values in the
01294 current row or the insert row. The <code>updateXXX</code> methods do not
01295 update the underlying database; instead the <code>updateRow</code> or
01296 <code>insertRow</code> methods are called to update the database.
01297
01298 @param columnIndex the first column is 1, the second is 2, ...
01299 @param x the new column value
01300 }
01301 procedure TZAbstractCachedResultSet.UpdateTimestamp(ColumnIndex: Integer;
01302 Value: TDateTime);
01303 begin
01304 {$IFNDEF DISABLE_CHECKING}
01305 CheckUpdatable;
01306 {$ENDIF}
01307 PrepareRowForUpdates;
01308 FRowAccessor.SetTimestamp(ColumnIndex, Value);
01309 end;
01310
01311 {**
01312 Updates the designated column with an ascii stream value.
01313 The <code>updateXXX</code> methods are used to update column values in the
01314 current row or the insert row. The <code>updateXXX</code> methods do not
01315 update the underlying database; instead the <code>updateRow</code> or
01316 <code>insertRow</code> methods are called to update the database.
01317
01318 @param columnIndex the first column is 1, the second is 2, ...
01319 @param x the new column value
01320 }
01321 procedure TZAbstractCachedResultSet.UpdateAsciiStream(ColumnIndex: Integer;
01322 Value: TStream);
01323 begin
01324 {$IFNDEF DISABLE_CHECKING}
01325 CheckUpdatable;
01326 {$ENDIF}
01327 PrepareRowForUpdates;
01328 FRowAccessor.SetAsciiStream(ColumnIndex, Value);
01329 end;
01330
01331 {**
01332 Updates the designated column with a binary stream value.
01333 The <code>updateXXX</code> methods are used to update column values in the
01334 current row or the insert row. The <code>updateXXX</code> methods do not
01335 update the underlying database; instead the <code>updateRow</code> or
01336 <code>insertRow</code> methods are called to update the database.
01337
01338 @param columnIndex the first column is 1, the second is 2, ...
01339 @param x the new column value
01340 @param length the length of the stream
01341 }
01342 procedure TZAbstractCachedResultSet.UpdateBinaryStream(
01343 ColumnIndex: Integer; Value: TStream);
01344 begin
01345 {$IFNDEF DISABLE_CHECKING}
01346 CheckUpdatable;
01347 {$ENDIF}
01348 PrepareRowForUpdates;
01349 FRowAccessor.SetBinaryStream(ColumnIndex, Value);
01350 end;
01351
01352 {**
01353 Updates the designated column with a character stream value.
01354 The <code>updateXXX</code> methods are used to update column values in the
01355 current row or the insert row. The <code>updateXXX</code> methods do not
01356 update the underlying database; instead the <code>updateRow</code> or
01357 <code>insertRow</code> methods are called to update the database.
01358
01359 @param columnIndex the first column is 1, the second is 2, ...
01360 @param x the new column value
01361 }
01362 procedure TZAbstractCachedResultSet.UpdateUnicodeStream(
01363 ColumnIndex: Integer; Value: TStream);
01364 begin
01365 {$IFNDEF DISABLE_CHECKING}
01366 CheckUpdatable;
01367 {$ENDIF}
01368 PrepareRowForUpdates;
01369 FRowAccessor.SetUnicodeStream(ColumnIndex, Value);
01370 end;
01371
01372 //---------------------------------------------------------------------
01373 // Processing methods
01374 //---------------------------------------------------------------------
01375
01376 {**
01377 Moves the cursor to the given row number in
01378 this <code>ResultSet</code> object.
01379
01380 <p>If the row number is positive, the cursor moves to
01381 the given row number with respect to the
01382 beginning of the result set. The first row is row 1, the second
01383 is row 2, and so on.
01384
01385 <p>If the given row number is negative, the cursor moves to
01386 an absolute row position with respect to
01387 the end of the result set. For example, calling the method
01388 <code>absolute(-1)</code> positions the
01389 cursor on the last row; calling the method <code>absolute(-2)</code>
01390 moves the cursor to the next-to-last row, and so on.
01391
01392 <p>An attempt to position the cursor beyond the first/last row in
01393 the result set leaves the cursor before the first row or after
01394 the last row.
01395
01396 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
01397 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
01398 is the same as calling <code>last()</code>.
01399
01400 @return <code>true</code> if the cursor is on the result set;
01401 <code>false</code> otherwise
01402 }
01403 function TZAbstractCachedResultSet.MoveAbsolute(Row: Integer): Boolean;
01404 begin
01405 {$IFNDEF DISABLE_CHECKING}
01406 CheckClosed;
01407 if (ResultSetType = rtForwardOnly) and (Row < RowNo) then
01408 RaiseForwardOnlyException;
01409 {$ENDIF}
01410
01411 if (Row >= 0) and (Row <= LastRowNo + 1) then
01412 begin
01413 RowNo := Row;
01414 if (Row >= 1) and (Row <= LastRowNo) then
01415 begin
01416 Result := True;
01417 FSelectedRow := PZRowBuffer(FRowsList[Row - 1]);
01418 RowAccessor.RowBuffer := FSelectedRow;
01419 end
01420 else
01421 begin
01422 Result := False;
01423 FSelectedRow := nil;
01424 RowAccessor.RowBuffer := FSelectedRow;
01425 end;
01426 end else
01427 Result := False;
01428 end;
01429
01430 {**
01431 Indicates whether the current row has been updated. The value returned
01432 depends on whether or not the result set can detect updates.
01433
01434 @return <code>true</code> if the row has been visibly updated
01435 by the owner or another, and updates are detected
01436 }
01437 function TZAbstractCachedResultSet.RowUpdated: Boolean;
01438 var
01439 CurrentRow: PZRowBuffer;
01440 begin
01441 if (RowNo >= 1) and (RowNo <= LastRowNo) then
01442 begin
01443 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
01444 Result := CurrentRow^.UpdateType = utModified;
01445 end else
01446 Result := False;
01447 end;
01448
01449 {**
01450 Indicates whether the current row has had an insertion.
01451 The value returned depends on whether or not this
01452 <code>ResultSet</code> object can detect visible inserts.
01453
01454 @return <code>true</code> if a row has had an insertion
01455 and insertions are detected; <code>false</code> otherwise
01456 }
01457 function TZAbstractCachedResultSet.RowInserted: Boolean;
01458 var
01459 CurrentRow: PZRowBuffer;
01460 begin
01461 if (RowNo >= 1) and (RowNo <= LastRowNo) then
01462 begin
01463 CurrentRow := PZRowBuffer(FRowsList[RowNo - 1]);
01464 Result := CurrentRow^.UpdateType = utInserted;
01465 end else
01466 Result := False;
01467 end;
01468
01469 {**
01470 Indicates whether a row has been deleted. A deleted row may leave
01471 a visible "hole" in a result set. This method can be used to
01472 detect holes in a result set. The value returned depends on whether
01473 or not this <code>ResultSet</code> object can detect deletions.
01474
01475 @return <code>true</code> if a row was deleted and deletions are detected;
01476 <code>false</code> otherwise
01477 }
01478 function TZAbstractCachedResultSet.RowDeleted: Boolean;
01479 var
01480 UpdateType: TZRowUpdateType;
01481 begin
01482 if (RowNo >= 1) and (RowNo <= LastRowNo) then
01483 begin
01484 UpdateType := PZRowBuffer(FRowsList[RowNo - 1])^.UpdateType;
01485 Result := UpdateType = utDeleted;
01486 end else
01487 Result := False;
01488 end;
01489
01490 {**
01491 Inserts the contents of the insert row into this
01492 <code>ResultSet</code> object and into the database.
01493 The cursor must be on the insert row when this method is called.
01494 }
01495 procedure TZAbstractCachedResultSet.InsertRow;
01496 var
01497 TempRow: PZRowBuffer;
01498 begin
01499 CheckClosed;
01500
01501 { Creates a new row. }
01502 TempRow := FRowAccessor.RowBuffer;
01503 FRowAccessor.Alloc;
01504 FRowAccessor.MoveFrom(FInsertedRow);
01505 FRowAccessor.RowBuffer^.UpdateType := utInserted;
01506 FRowAccessor.RowBuffer^.Index := GetNextRowIndex;
01507
01508 AppendRow(FRowAccessor.RowBuffer);
01509
01510 { Posts non-cached updates. }
01511 if not FCachedUpdates then
01512 begin
01513 try
01514 PostUpdates;
01515 except
01516 on E: Exception do
01517 begin
01518 { Restore the previous state. }
01519 FRowAccessor.DisposeBuffer(FInitialRowsList[FInitialRowsList.Count - 1]);
01520 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
01521 FRowAccessor.DisposeBuffer(FCurrentRowsList[FCurrentRowsList.Count - 1]);
01522 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
01523 FRowAccessor.RowBuffer := TempRow;
01524
01525 { Reraises the exception. }
01526 RaiseSQLException(E);
01527 end;
01528 end;
01529 end;
01530
01531 FRowsList.Add(FRowAccessor.RowBuffer);
01532 LastRowNo := FRowsList.Count;
01533 MoveAbsolute(LastRowNo);
01534 end;
01535
01536 {**
01537 Updates the underlying database with the new contents of the
01538 current row of this <code>ResultSet</code> object.
01539 This method cannot be called when the cursor is on the insert row.
01540 }
01541 procedure TZAbstractCachedResultSet.UpdateRow;
01542 begin
01543 CheckUpdatable;
01544 if (RowNo < 1) or (RowNo > LastRowNo) then
01545 raise EZSQLException.Create(SCanNotUpdateEmptyRow);
01546
01547 if PZRowBuffer(FRowsList[RowNo - 1]).UpdateType = utDeleted then
01548 raise EZSQLException.Create(SCanNotUpdateDeletedRow);
01549
01550 if FSelectedRow <> FUpdatedRow then Exit;
01551
01552 AppendRow(FRowsList[RowNo - 1]);
01553
01554 FSelectedRow := PZRowBuffer(FRowsList[RowNo - 1]);
01555 FRowAccessor.CopyBuffer(FUpdatedRow, FSelectedRow);
01556 FRowAccessor.RowBuffer := FSelectedRow;
01557 if FSelectedRow.UpdateType = utUnmodified then
01558 FSelectedRow.UpdateType := utModified;
01559
01560 { Posts non-cached updates. }
01561 if not FCachedUpdates then
01562 begin
01563 try
01564 PostUpdates;
01565 except
01566 on E: Exception do
01567 begin
01568 { Restore the previous state. }
01569 FRowAccessor.DisposeBuffer(FRowsList[RowNo - 1]);
01570 FRowsList[RowNo - 1] := FInitialRowsList[FInitialRowsList.Count - 1];
01571 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
01572 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
01573
01574 FSelectedRow := PZRowBuffer(FRowsList[RowNo - 1]);
01575 FRowAccessor.RowBuffer := FSelectedRow;
01576
01577 { Reraises the exception. }
01578 RaiseSQLException(E);
01579 end;
01580 end;
01581 end;
01582 end;
01583
01584 {**
01585 Deletes the current row from this <code>ResultSet</code> object
01586 and from the underlying database. This method cannot be called when
01587 the cursor is on the insert row.
01588 }
01589 procedure TZAbstractCachedResultSet.DeleteRow;
01590 begin
01591 CheckUpdatable;
01592 if (RowNo < 1) or (RowNo > LastRowNo) or (FSelectedRow = nil) then
01593 raise EZSQLException.Create(SCanNotDeleteEmptyRow);
01594
01595 if FSelectedRow^.UpdateType = utInserted then
01596 RevertRecord
01597 else begin
01598 AppendRow(FRowsList[RowNo - 1]);
01599
01600 FSelectedRow^.UpdateType := utDeleted;
01601 if FSelectedRow = FUpdatedRow then
01602 FRowAccessor.CopyBuffer(FUpdatedRow, FRowsList[RowNo - 1]);
01603
01604 { Posts non-cached updates. }
01605 if not FCachedUpdates then
01606 begin
01607 try
01608 PostUpdates;
01609 except
01610 on E: Exception do
01611 begin
01612 { Restores the previous state. }
01613 FRowAccessor.DisposeBuffer(FRowsList[RowNo - 1]);
01614 FRowsList[RowNo - 1] := FInitialRowsList[FInitialRowsList.Count - 1];
01615 FSelectedRow := FRowsList[RowNo - 1];
01616 FInitialRowsList.Delete(FInitialRowsList.Count - 1);
01617 FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
01618
01619 { Rethrows the exception. }
01620 RaiseSQLException(E);
01621 end;
01622 end;
01623 end;
01624 end;
01625 end;
01626
01627 {**
01628 Cancels the updates made to the current row in this
01629 <code>ResultSet</code> object.
01630 This method may be called after calling an
01631 <code>updateXXX</code> method(s) and before calling
01632 the method <code>updateRow</code> to roll back
01633 the updates made to a row. If no updates have been made or
01634 <code>updateRow</code> has already been called, this method has no
01635 effect.
01636 }
01637 procedure TZAbstractCachedResultSet.CancelRowUpdates;
01638 begin
01639 MoveAbsolute(RowNo);
01640 end;
01641
01642 {**
01643 Moves the cursor to the insert row. The current cursor position is
01644 remembered while the cursor is positioned on the insert row.
01645
01646 The insert row is a special row associated with an updatable
01647 result set. It is essentially a buffer where a new row may
01648 be constructed by calling the <code>updateXXX</code> methods prior to
01649 inserting the row into the result set.
01650
01651 Only the <code>updateXXX</code>, <code>getXXX</code>,
01652 and <code>insertRow</code> methods may be
01653 called when the cursor is on the insert row. All of the columns in
01654 a result set must be given a value each time this method is
01655 called before calling <code>insertRow</code>.
01656 An <code>updateXXX</code> method must be called before a
01657 <code>getXXX</code> method can be called on a column value.
01658 }
01659 procedure TZAbstractCachedResultSet.MoveToInsertRow;
01660 begin
01661 CheckClosed;
01662 FRowAccessor.RowBuffer := FInsertedRow;
01663 end;
01664
01665 {**
01666 Moves the cursor to the remembered cursor position, usually the
01667 current row. This method has no effect if the cursor is not on
01668 the insert row.
01669 }
01670 procedure TZAbstractCachedResultSet.MoveToCurrentRow;
01671 begin
01672 CheckClosed;
01673 if (RowNo >= 1) and (RowNo <= LastRowNo) then
01674 FRowAccessor.RowBuffer := FSelectedRow
01675 else FRowAccessor.RowBuffer := nil;
01676 end;
01677
01678 {**
01679 Compares fields from two row buffers.
01680 @param Row1 the first row buffer to compare.
01681 @param Row2 the second row buffer to compare.
01682 @param ColumnIndices column indices to compare.
01683 @param ColumnDirs compare direction for each columns.
01684 }
01685 function TZAbstractCachedResultSet.CompareRows(Row1, Row2: Integer;
01686 const ColumnIndices: TIntegerDynArray; const ColumnDirs: TBooleanDynArray): Integer;
01687 var
01688 RowBuffer1, RowBuffer2: PZRowBuffer;
01689 begin
01690 {$IFNDEF DISABLE_CHECKING}
01691 if ResultSetType = rtForwardOnly then
01692 RaiseForwardOnlyException;
01693 {$ENDIF}
01694 RowBuffer1 := PZRowBuffer(FRowsList[Row1 - 1]);
01695 RowBuffer2 := PZRowBuffer(FRowsList[Row2 - 1]);
01696 Result := FRowAccessor.CompareBuffers(RowBuffer1, RowBuffer2,
01697 ColumnIndices, ColumnDirs);
01698 end;
01699
01700 { TZCachedResultSet }
01701
01702 {**
01703 Creates this object and assignes the main properties.
01704 @param ResultSet a wrapped resultset object.
01705 @param Resolver a cached updates resolver object.
01706 }
01707 constructor TZCachedResultSet.Create(ResultSet: IZResultSet; SQL: string;
01708 Resolver: IZCachedResolver);
01709 begin
01710 inherited Create(ResultSet.GetStatement, SQL, nil);
01711 FResultSet := ResultSet;
01712 FResolver := Resolver;
01713 {BEGIN PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
01714 FNativeResolver := Resolver;
01715 {END PATCH [1214009] CalcDefaults in TZUpdateSQL and Added Methods to GET the DB NativeResolver}
01716 Open;
01717 end;
01718
01719 {**
01720 Destroys this object and cleanups the memory.
01721 }
01722 destructor TZCachedResultSet.Destroy;
01723 begin
01724 inherited Destroy;
01725 end;
01726
01727 {**
01728 Fetches one row from the wrapped result set object.
01729 @return <code>True</code> if row was successfuly fetched
01730 or <code>False</code> otherwise.
01731 }
01732 function TZCachedResultSet.Fetch: Boolean;
01733 var
01734 I: Integer;
01735 TempRow: PZRowBuffer;
01736 begin
01737 Result := FResultSet.Next;
01738 if not Result or ((MaxRows > 0) and (LastRowNo >= MaxRows)) then
01739 Exit;
01740
01741 TempRow := RowAccessor.RowBuffer;
01742 try
01743 RowAccessor.Alloc;
01744 RowAccessor.RowBuffer.Index := GetNextRowIndex;
01745 RowAccessor.RowBuffer.UpdateType := utUnmodified;
01746
01747 for I := 1 to ColumnsInfo.Count do
01748 begin
01749 case TZColumnInfo(ColumnsInfo[I - 1]).ColumnType of
01750 stBoolean: RowAccessor.SetBoolean(I, ResultSet.GetBoolean(I));
01751 stByte: RowAccessor.SetByte(I, ResultSet.GetByte(I));
01752 stShort: RowAccessor.SetShort(I, ResultSet.GetShort(I));
01753 stInteger: RowAccessor.SetInt(I, ResultSet.GetInt(I));
01754 stLong: RowAccessor.SetLong(I, ResultSet.GetLong(I));
01755 stFloat: RowAccessor.SetFloat(I, ResultSet.GetFloat(I));
01756 stDouble: RowAccessor.SetDouble(I, ResultSet.GetDouble(I));
01757 stBigDecimal: RowAccessor.SetBigDecimal(I, ResultSet.GetBigDecimal(I));
01758 stString: RowAccessor.SetPChar(I, ResultSet.GetPChar(I));
01759 stUnicodeString: RowAccessor.SetUnicodeString(I, ResultSet.GetUnicodeString(I));
01760 stBytes: RowAccessor.SetBytes(I, ResultSet.GetBytes(I));
01761 stDate: RowAccessor.SetDate(I, ResultSet.GetDate(I));
01762 stTime: RowAccessor.SetTime(I, ResultSet.GetTime(I));
01763 stTimestamp: RowAccessor.SetTimestamp(I, ResultSet.GetTimestamp(I));
01764 stAsciiStream, stUnicodeStream, stBinaryStream:
01765 RowAccessor.SetBlob(I, ResultSet.GetBlob(I));
01766 end;
01767 if ResultSet.WasNull then
01768 RowAccessor.SetNull(I);
01769 end;
01770
01771 RowsList.Add(RowAccessor.RowBuffer);
01772 LastRowNo := RowsList.Count;
01773 finally
01774 RowAccessor.RowBuffer := TempRow;
01775 end;
01776 end;
01777
01778 {**
01779 Fetches all of the rest rows from the wrapped result set.
01780 }
01781 procedure TZCachedResultSet.FetchAll;
01782 begin
01783 while Fetch do;
01784 end;
01785
01786 {**
01787 Opens this recordset.
01788 }
01789 procedure TZCachedResultSet.Open;
01790 var
01791 I: Integer;
01792 ColumnInfo: TZColumnInfo;
01793 MetaData : IZResultSetMetaData;
01794 begin
01795 ColumnsInfo.Clear;
01796 MetaData := FResultSet.GetMetadata;
01797 for I := 1 to Metadata.GetColumnCount do
01798 begin
01799 ColumnInfo := TZColumnInfo.Create;
01800 with ColumnInfo do
01801 begin
01802 Currency := Metadata.IsCurrency(I);
01803 Signed := Metadata.IsSigned(I);
01804 ColumnDisplaySize := Metadata.GetColumnDisplaySize(I);
01805 ColumnLabel := Metadata.GetColumnLabel(I);
01806 Precision := Metadata.GetPrecision(I);
01807 Scale := Metadata.GetScale(I);
01808 ColumnType := Metadata.GetColumnType(I);
01809 end;
01810 ColumnsInfo.Add(ColumnInfo);
01811 end;
01812
01813 inherited Open;
01814 end;
01815
01816 {**
01817 Releases this <code>ResultSet</code> object's database and
01818 JDBC resources immediately instead of waiting for
01819 this to happen when it is automatically closed.
01820
01821 <P><B>Note:</B> A <code>ResultSet</code> object
01822 is automatically closed by the
01823 <code>Statement</code> object that generated it when
01824 that <code>Statement</code> object is closed,
01825 re-executed, or is used to retrieve the next result from a
01826 sequence of multiple results. A <code>ResultSet</code> object
01827 is also automatically closed when it is garbage collected.
01828 }
01829 procedure TZCachedResultSet.Close;
01830 begin
01831 inherited Close;
01832 ColumnsInfo.Clear;
01833 FResultSet := nil;
01834 end;
01835
01836 {**
01837 Retrieves the number, types and properties of
01838 this <code>ResultSet</code> object's columns.
01839 @return the description of this <code>ResultSet</code> object's columns
01840 }
01841 function TZCachedResultSet.GetMetadata: IZResultSetMetadata;
01842 begin
01843 Result := ResultSet.GetMetadata;
01844 end;
01845
01846 {**
01847 Indicates whether the cursor is after the last row in
01848 this <code>ResultSet</code> object.
01849
01850 @return <code>true</code> if the cursor is after the last row;
01851 <code>false</code> if the cursor is at any other position or the
01852 result set contains no rows
01853 }
01854 function TZCachedResultSet.IsAfterLast: Boolean;
01855 begin
01856 FetchAll;
01857 Result := inherited IsAfterLast;
01858 end;
01859
01860 {**
01861 Moves the cursor to the end of
01862 this <code>ResultSet</code> object, just after the
01863 last row. This method has no effect if the result set contains no rows.
01864 }
01865 procedure TZCachedResultSet.AfterLast;
01866 begin
01867 FetchAll;
01868 inherited AfterLast;
01869 end;
01870
01871 {**
01872 Indicates whether the cursor is on the last row of
01873 this <code>ResultSet</code> object.
01874 Note: Calling the method <code>isLast</code> may be expensive
01875 because the JDBC driver
01876 might need to fetch ahead one row in order to determine
01877 whether the current row is the last row in the result set.
01878
01879 @return <code>true</code> if the cursor is on the last row;
01880 <code>false</code> otherwise
01881 }
01882 function TZCachedResultSet.IsLast: Boolean;
01883 begin
01884 FetchAll;
01885 Result := inherited IsLast;
01886 end;
01887
01888 {**
01889 Moves the cursor to the last row in
01890 this <code>ResultSet</code> object.
01891
01892 @return <code>true</code> if the cursor is on a valid row;
01893 <code>false</code> if there are no rows in the result set
01894 }
01895 function TZCachedResultSet.Last: Boolean;
01896 begin
01897 FetchAll;
01898 Result := inherited Last;
01899 end;
01900
01901 {**
01902 Moves the cursor to the given row number in
01903 this <code>ResultSet</code> object.
01904
01905 <p>If the row number is positive, the cursor moves to
01906 the given row number with respect to the
01907 beginning of the result set. The first row is row 1, the second
01908 is row 2, and so on.
01909
01910 <p>If the given row number is negative, the cursor moves to
01911 an absolute row position with respect to
01912 the end of the result set. For example, calling the method
01913 <code>absolute(-1)</code> positions the
01914 cursor on the last row; calling the method <code>absolute(-2)</code>
01915 moves the cursor to the next-to-last row, and so on.
01916
01917 <p>An attempt to position the cursor beyond the first/last row in
01918 the result set leaves the cursor before the first row or after
01919 the last row.
01920
01921 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
01922 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
01923 is the same as calling <code>last()</code>.
01924
01925 @return <code>true</code> if the cursor is on the result set;
01926 <code>false</code> otherwise
01927 }
01928 function TZCachedResultSet.MoveAbsolute(Row: Integer): Boolean;
01929 begin
01930 { Checks for maximum row. }
01931 Result := False;
01932 if (MaxRows > 0) and (Row > MaxRows) then
01933 Exit;
01934
01935 { Processes negative rows }
01936 if Row < 0 then
01937 begin
01938 FetchAll;
01939 Row := LastRowNo - Row + 1;
01940 if Row < 0 then Row := 0;
01941 end else
01942 { Processes moving after last row }
01943 while (LastRowNo < Row) and Fetch do;
01944
01945 Result := inherited MoveAbsolute(Row);
01946 end;
01947
01948 end.
01949