00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Interbase Database Connectivity Classes }
00005 { }
00006 { Originally written by Sergey Merkuriev }
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 ZDbcInterbase6ResultSet;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 Classes, ZSysUtils, ZDbcIntfs, ZDbcResultSet, ZDbcInterbase6,
00062 ZPlainFirebirdInterbaseConstants,
00063 ZCompatibility, ZDbcResultSetMetadata, ZDbcInterbase6Utils, ZMessages;
00064
00065 type
00066
00067 {** Implements Interbase ResultSet. }
00068 TZInterbase6ResultSet = class(TZAbstractResultSet)
00069 private
00070 FCachedBlob: boolean;
00071 FFetchStat: Integer;
00072 FCursorName: string;
00073 FStmtHandle: TISC_STMT_HANDLE;
00074 FSqlData: IZResultSQLDA;
00075 FParamsSqlData: IZParamsSQLDA;
00076 FIBConnection: IZInterbase6Connection;
00077 protected
00078 procedure Open; override;
00079 function GetFieldValue(ColumnIndex: Integer): Variant;
00080 public
00081 constructor Create(Statement: IZStatement; SQL: string;
00082 var StatementHandle: TISC_STMT_HANDLE; CursorName: string;
00083 SqlData: IZResultSQLDA; ParamsSqlData: IZParamsSQLDA;
00084 CachedBlob: boolean);
00085 destructor Destroy; override;
00086
00087 procedure Close; override;
00088
00089 function GetCursorName: string; override;
00090
00091 function IsNull(ColumnIndex: Integer): Boolean; override;
00092 function GetString(ColumnIndex: Integer): string; override;
00093 function GetBoolean(ColumnIndex: Integer): Boolean; override;
00094 function GetByte(ColumnIndex: Integer): ShortInt; override;
00095 function GetShort(ColumnIndex: Integer): SmallInt; override;
00096 function GetInt(ColumnIndex: Integer): Integer; override;
00097 function GetLong(ColumnIndex: Integer): Int64; override;
00098 function GetFloat(ColumnIndex: Integer): Single; override;
00099 function GetDouble(ColumnIndex: Integer): Double; override;
00100 function GetBigDecimal(ColumnIndex: Integer): Extended; override;
00101 function GetBytes(ColumnIndex: Integer): TByteDynArray; override;
00102 function GetDate(ColumnIndex: Integer): TDateTime; override;
00103 function GetTime(ColumnIndex: Integer): TDateTime; override;
00104 function GetTimestamp(ColumnIndex: Integer): TDateTime; override;
00105 function GetBlob(ColumnIndex: Integer): IZBlob; override;
00106
00107 function MoveAbsolute(Row: Integer): Boolean; override;
00108 function Next: Boolean; override;
00109 end;
00110
00111 {** Implements external blob wrapper object for PostgreSQL. }
00112 TZInterbase6Blob = class(TZAbstractBlob)
00113 private
00114 FBlobId: TISC_QUAD;
00115 FBlobRead: Boolean;
00116 FIBConnection: IZInterbase6Connection;
00117 protected
00118 procedure ReadBlob;
00119 public
00120 constructor Create(IBConnection: IZInterbase6Connection;
00121 var BlobId: TISC_QUAD);
00122
00123 function IsEmpty: Boolean; override;
00124 function Clone: IZBlob; override;
00125 function GetStream: TStream; override;
00126 function GetString: string; override;
00127 function GetUnicodeString: WideString; override;
00128 function GetBytes: TByteDynArray; override;
00129 end;
00130
00131 implementation
00132
00133 uses
00134 {$IFNDEF VER130BELOW}
00135 Variants,
00136 {$ENDIF}
00137 SysUtils;
00138
00139 { TZInterbase6ResultSet }
00140
00141 {**
00142 Releases this <code>ResultSet</code> object's database and
00143 JDBC resources immediately instead of waiting for
00144 this to happen when it is automatically closed.
00145
00146 <P><B>Note:</B> A <code>ResultSet</code> object
00147 is automatically closed by the
00148 <code>Statement</code> object that generated it when
00149 that <code>Statement</code> object is closed,
00150 re-executed, or is used to retrieve the next result from a
00151 sequence of multiple results. A <code>ResultSet</code> object
00152 is also automatically closed when it is garbage collected.
00153 }
00154 procedure TZInterbase6ResultSet.Close;
00155 begin
00156 if FStmtHandle <> nil then
00157 begin
00158 { Free output allocated memory }
00159 FSqlData := nil;
00160 FParamsSqlData := nil;
00161 { Free allocate sql statement }
00162 FreeStatement(FIBConnection.GetPlainDriver, FStmtHandle);
00163 end;
00164 inherited Close;
00165 end;
00166
00167 {**
00168 Constructs this object, assignes main properties and
00169 opens the record set.
00170 @param Statement a related SQL statement object.
00171 @param handle a Interbase6 database connect handle.
00172 @param the statement previously prepared
00173 @param the sql out data previously allocated
00174 @param the Interbase sql dialect
00175 }
00176 constructor TZInterbase6ResultSet.Create(Statement: IZStatement; SQL: string;
00177 var StatementHandle: TISC_STMT_HANDLE; CursorName: string;
00178 SqlData: IZResultSQLDA; ParamsSqlData: IZParamsSQLDA; CachedBlob: boolean);
00179 begin
00180 inherited Create(Statement, SQL, nil);
00181
00182 FFetchStat := 0;
00183 FSqlData := SqlData;
00184 FCursorName := CursorName;
00185 FCachedBlob := CachedBlob;
00186 FIBConnection := Statement.GetConnection as IZInterbase6Connection;
00187
00188 FParamsSqlData := ParamsSqlData;
00189 FStmtHandle := StatementHandle;
00190 ResultSetType := rtForwardOnly;
00191 ResultSetConcurrency := rcReadOnly;
00192
00193 Open;
00194 end;
00195
00196 {**
00197 Free memory and destriy component
00198 }
00199 destructor TZInterbase6ResultSet.Destroy;
00200 begin
00201 if not Closed then
00202 Close;
00203 inherited Destroy;
00204 end;
00205
00206 {**
00207 Return field value by it index
00208 @param the index column 0 first, 1 second ...
00209 @return the field value as variant type
00210 }
00211 function TZInterbase6ResultSet.GetFieldValue(ColumnIndex: Integer): Variant;
00212 begin
00213 CheckClosed;
00214 Result := FSqlData.GetValue(ColumnIndex);
00215 end;
00216
00217 {**
00218 Gets the value of the designated column in the current row
00219 of this <code>ResultSet</code> object as
00220 a <code>java.sql.BigDecimal</code> in the Java programming language.
00221
00222 @param columnIndex the first column is 1, the second is 2, ...
00223 @param scale the number of digits to the right of the decimal point
00224 @return the column value; if the value is SQL <code>NULL</code>, the
00225 value returned is <code>null</code>
00226 }
00227 function TZInterbase6ResultSet.GetBigDecimal(ColumnIndex: Integer): Extended;
00228 begin
00229 CheckClosed;
00230 CheckColumnConvertion(ColumnIndex, stBigDecimal);
00231 Result := FSqlData.GetBigDecimal(ColumnIndex - 1);
00232 LastWasNull := IsNull(ColumnIndex);
00233 end;
00234
00235 {**
00236 Returns the value of the designated column in the current row
00237 of this <code>ResultSet</code> object as a <code>Blob</code> object
00238 in the Java programming language.
00239
00240 @param ColumnIndex the first column is 1, the second is 2, ...
00241 @return a <code>Blob</code> object representing the SQL <code>BLOB</code> value in
00242 the specified column
00243 }
00244 function TZInterbase6ResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
00245 var
00246 Size: Integer;
00247 Buffer: Pointer;
00248 BlobId: TISC_QUAD;
00249 begin
00250 Result := nil;
00251 CheckClosed;
00252 CheckBlobColumn(ColumnIndex);
00253
00254 LastWasNull := IsNull(ColumnIndex);
00255 if LastWasNull then Exit;
00256
00257 if FCachedBlob then
00258 begin
00259 try
00260 BlobId := FSqlData.GetQuad(ColumnIndex - 1);
00261 with FIBConnection do
00262 ReadBlobBufer(GetPlainDriver, GetDBHandle, GetTrHandle,
00263 BlobId, Size, Buffer);
00264 Result := TZAbstractBlob.CreateWithData(Buffer, Size);
00265 finally
00266 FreeMem(Buffer, Size);
00267 end;
00268 end
00269 else begin
00270 BlobId := FSqlData.GetQuad(ColumnIndex - 1);
00271 Result := TZInterbase6Blob.Create(FIBConnection, BlobId);
00272 end;
00273 end;
00274
00275 {**
00276 Gets the value of the designated column in the current row
00277 of this <code>ResultSet</code> object as
00278 a <code>boolean</code> in the Java programming language.
00279
00280 @param columnIndex the first column is 1, the second is 2, ...
00281 @return the column value; if the value is SQL <code>NULL</code>, the
00282 value returned is <code>false</code>
00283 }
00284 function TZInterbase6ResultSet.GetBoolean(ColumnIndex: Integer): Boolean;
00285 begin
00286 CheckClosed;
00287 CheckColumnConvertion(ColumnIndex, stBoolean);
00288 Result := FSqlData.GetBoolean(ColumnIndex - 1);
00289 LastWasNull := IsNull(ColumnIndex);
00290 end;
00291
00292 {**
00293 Gets the value of the designated column in the current row
00294 of this <code>ResultSet</code> object as
00295 a <code>byte</code> in the Java programming language.
00296
00297 @param columnIndex the first column is 1, the second is 2, ...
00298 @return the column value; if the value is SQL <code>NULL</code>, the
00299 value returned is <code>0</code>
00300 }
00301 function TZInterbase6ResultSet.GetByte(ColumnIndex: Integer): ShortInt;
00302 begin
00303 CheckClosed;
00304 CheckColumnConvertion(ColumnIndex, stByte);
00305 Result := FSqlData.GetByte(ColumnIndex - 1);
00306 LastWasNull := IsNull(ColumnIndex);
00307 end;
00308
00309 {**
00310 Gets the value of the designated column in the current row
00311 of this <code>ResultSet</code> object as
00312 a <code>byte</code> array in the Java programming language.
00313 The bytes represent the raw values returned by the driver.
00314
00315 @param columnIndex the first column is 1, the second is 2, ...
00316 @return the column value; if the value is SQL <code>NULL</code>, the
00317 value returned is <code>null</code>
00318 }
00319 function TZInterbase6ResultSet.GetBytes(
00320 ColumnIndex: Integer): TByteDynArray;
00321 begin
00322 CheckClosed;
00323 CheckColumnConvertion(ColumnIndex, stBytes);
00324 Result := FSqlData.GetBytes(ColumnIndex - 1);
00325 LastWasNull := IsNull(ColumnIndex);
00326 end;
00327
00328 {**
00329 Gets the value of the designated column in the current row
00330 of this <code>ResultSet</code> object as
00331 a <code>java.sql.Date</code> object in the Java programming language.
00332
00333 @param columnIndex the first column is 1, the second is 2, ...
00334 @return the column value; if the value is SQL <code>NULL</code>, the
00335 value returned is <code>null</code>
00336 }
00337 function TZInterbase6ResultSet.GetDate(ColumnIndex: Integer): TDateTime;
00338 begin
00339 CheckClosed;
00340 CheckColumnConvertion(ColumnIndex, stDate);
00341 Result := FSqlData.GetDate(ColumnIndex - 1);
00342 LastWasNull := IsNull(ColumnIndex);
00343 end;
00344
00345 {**
00346 Gets the value of the designated column in the current row
00347 of this <code>ResultSet</code> object as
00348 a <code>double</code> in the Java programming language.
00349
00350 @param columnIndex the first column is 1, the second is 2, ...
00351 @return the column value; if the value is SQL <code>NULL</code>, the
00352 value returned is <code>0</code>
00353 }
00354 function TZInterbase6ResultSet.GetDouble(ColumnIndex: Integer): Double;
00355 begin
00356 CheckClosed;
00357 CheckColumnConvertion(ColumnIndex, stDouble);
00358 Result := FSqlData.GetDouble(ColumnIndex - 1);
00359 LastWasNull := IsNull(ColumnIndex);
00360 end;
00361
00362 {**
00363 Gets the value of the designated column in the current row
00364 of this <code>ResultSet</code> object as
00365 a <code>float</code> in the Java programming language.
00366
00367 @param columnIndex the first column is 1, the second is 2, ...
00368 @return the column value; if the value is SQL <code>NULL</code>, the
00369 value returned is <code>0</code>
00370 }
00371 function TZInterbase6ResultSet.GetFloat(ColumnIndex: Integer): Single;
00372 begin
00373 CheckClosed;
00374 CheckColumnConvertion(ColumnIndex, stFloat);
00375 Result := FSqlData.GetFloat(ColumnIndex - 1);
00376 LastWasNull := IsNull(ColumnIndex);
00377 end;
00378
00379 {**
00380 Gets the value of the designated column in the current row
00381 of this <code>ResultSet</code> object as
00382 an <code>int</code> in the Java programming language.
00383
00384 @param columnIndex the first column is 1, the second is 2, ...
00385 @return the column value; if the value is SQL <code>NULL</code>, the
00386 value returned is <code>0</code>
00387 }
00388 function TZInterbase6ResultSet.GetInt(ColumnIndex: Integer): Integer;
00389 begin
00390 CheckClosed;
00391 CheckColumnConvertion(ColumnIndex, stInteger);
00392 Result := FSqlData.GetInt(ColumnIndex - 1);
00393 LastWasNull := IsNull(ColumnIndex);
00394 end;
00395
00396 {**
00397 Gets the value of the designated column in the current row
00398 of this <code>ResultSet</code> object as
00399 a <code>long</code> in the Java programming language.
00400
00401 @param columnIndex the first column is 1, the second is 2, ...
00402 @return the column value; if the value is SQL <code>NULL</code>, the
00403 value returned is <code>0</code>
00404 }
00405 function TZInterbase6ResultSet.GetLong(ColumnIndex: Integer): Int64;
00406 begin
00407 CheckClosed;
00408 CheckColumnConvertion(ColumnIndex, stLong);
00409 Result := FSqlData.GetLong(ColumnIndex - 1);
00410 LastWasNull := IsNull(ColumnIndex);
00411 end;
00412
00413 {**
00414 Gets the value of the designated column in the current row
00415 of this <code>ResultSet</code> object as
00416 a <code>short</code> in the Java programming language.
00417
00418 @param columnIndex the first column is 1, the second is 2, ...
00419 @return the column value; if the value is SQL <code>NULL</code>, the
00420 value returned is <code>0</code>
00421 }
00422 function TZInterbase6ResultSet.GetShort(ColumnIndex: Integer): SmallInt;
00423 begin
00424 CheckClosed;
00425 CheckColumnConvertion(ColumnIndex, stShort);
00426 Result := FSqlData.GetShort(ColumnIndex - 1);
00427 LastWasNull := IsNull(ColumnIndex);
00428 end;
00429
00430 {**
00431 Gets the value of the designated column in the current row
00432 of this <code>ResultSet</code> object as
00433 a <code>String</code> in the Java programming language.
00434
00435 @param columnIndex the first column is 1, the second is 2, ...
00436 @return the column value; if the value is SQL <code>NULL</code>, the
00437 value returned is <code>null</code>
00438 }
00439 function TZInterbase6ResultSet.GetString(ColumnIndex: Integer): string;
00440 begin
00441 CheckClosed;
00442 CheckColumnConvertion(ColumnIndex, stString);
00443 LastWasNull := IsNull(ColumnIndex);
00444 Result := FSqlData.GetString(ColumnIndex - 1);
00445 end;
00446
00447 {**
00448 Gets the value of the designated column in the current row
00449 of this <code>ResultSet</code> object as
00450 a <code>java.sql.Time</code> object in the Java programming language.
00451
00452 @param columnIndex the first column is 1, the second is 2, ...
00453 @return the column value; if the value is SQL <code>NULL</code>, the
00454 value returned is <code>null</code>
00455 }
00456 function TZInterbase6ResultSet.GetTime(ColumnIndex: Integer): TDateTime;
00457 begin
00458 CheckClosed;
00459 CheckColumnConvertion(ColumnIndex, stTime);
00460 Result := FSqlData.GetTime(ColumnIndex - 1);
00461 LastWasNull := IsNull(ColumnIndex);
00462 end;
00463
00464 {**
00465 Gets the value of the designated column in the current row
00466 of this <code>ResultSet</code> object as
00467 a <code>java.sql.Timestamp</code> object in the Java programming language.
00468
00469 @param columnIndex the first column is 1, the second is 2, ...
00470 @return the column value; if the value is SQL <code>NULL</code>, the
00471 value returned is <code>null</code>
00472 @exception SQLException if a database access error occurs
00473 }
00474 function TZInterbase6ResultSet.GetTimestamp(ColumnIndex: Integer): TDateTime;
00475 begin
00476 CheckClosed;
00477 CheckColumnConvertion(ColumnIndex, stTimestamp);
00478 Result := FSqlData.GetTimestamp(ColumnIndex - 1);
00479 LastWasNull := IsNull(ColumnIndex);
00480 end;
00481
00482 {**
00483 Indicates if the value of the designated column in the current row
00484 of this <code>ResultSet</code> object is Null.
00485
00486 @param columnIndex the first column is 1, the second is 2, ...
00487 @return if the value is SQL <code>NULL</code>, the
00488 value returned is <code>true</code>. <code>false</code> otherwise.
00489 }
00490 function TZInterbase6ResultSet.IsNull(ColumnIndex: Integer): Boolean;
00491 begin
00492 CheckClosed;
00493 Result := FSqlData.IsNull(ColumnIndex - 1);
00494 end;
00495
00496 {**
00497 Moves the cursor to the given row number in
00498 this <code>ResultSet</code> object.
00499
00500 <p>If the row number is positive, the cursor moves to
00501 the given row number with respect to the
00502 beginning of the result set. The first row is row 1, the second
00503 is row 2, and so on.
00504
00505 <p>If the given row number is negative, the cursor moves to
00506 an absolute row position with respect to
00507 the end of the result set. For example, calling the method
00508 <code>absolute(-1)</code> positions the
00509 cursor on the last row; calling the method <code>absolute(-2)</code>
00510 moves the cursor to the next-to-last row, and so on.
00511
00512 <p>An attempt to position the cursor beyond the first/last row in
00513 the result set leaves the cursor before the first row or after
00514 the last row.
00515
00516 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
00517 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
00518 is the same as calling <code>last()</code>.
00519
00520 @return <code>true</code> if the cursor is on the result set;
00521 <code>false</code> otherwise
00522 }
00523 function TZInterbase6ResultSet.MoveAbsolute(Row: Integer): Boolean;
00524 begin
00525 Result := False;
00526 RaiseForwardOnlyException;
00527 end;
00528
00529 {**
00530 Moves the cursor down one row from its current position.
00531 A <code>ResultSet</code> cursor is initially positioned
00532 before the first row; the first call to the method
00533 <code>next</code> makes the first row the current row; the
00534 second call makes the second row the current row, and so on.
00535
00536 <P>If an input stream is open for the current row, a call
00537 to the method <code>next</code> will
00538 implicitly close it. A <code>ResultSet</code> object's
00539 warning chain is cleared when a new row is read.
00540
00541 @return <code>true</code> if the new current row is valid;
00542 <code>false</code> if there are no more rows
00543 }
00544 function TZInterbase6ResultSet.Next: Boolean;
00545 var
00546 StatusVector: TARRAY_ISC_STATUS;
00547 begin
00548 { Checks for maximum row. }
00549 Result := False;
00550 if (MaxRows > 0) and (LastRowNo >= MaxRows) then
00551 Exit;
00552
00553 { Fetch row. }
00554 if (ResultSetType = rtForwardOnly) and (FFetchStat = 0) then
00555 begin
00556 with FIBConnection do
00557 begin
00558 FFetchStat := GetPlainDriver.isc_dsql_fetch(@StatusVector,
00559 @FStmtHandle, GetDialect, FSqlData.GetData);
00560 CheckInterbase6Error(GetPlainDriver, StatusVector);
00561 end;
00562
00563 if FFetchStat = 0 then
00564 begin
00565 RowNo := RowNo + 1;
00566 LastRowNo := RowNo;
00567 Result := True;
00568 end;
00569 end;
00570 end;
00571
00572 {**
00573 Opens this recordset.
00574 }
00575 procedure TZInterbase6ResultSet.Open;
00576 var
00577 I: Integer;
00578 FieldSqlType: TZSQLType;
00579 ColumnInfo: TZColumnInfo;
00580 begin
00581 if not Assigned(FStmtHandle) then
00582 raise EZSQLException.Create(SCanNotRetrieveResultSetData);
00583
00584 ColumnsInfo.Clear;
00585 for I := 0 to FSqlData.GetFieldCount - 1 do
00586 begin
00587 ColumnInfo := TZColumnInfo.Create;
00588 with ColumnInfo, FSqlData do
00589 begin
00590 FieldSqlType := GetFieldSqlType(I);
00591 ColumnName := GetFieldSqlName(I);
00592 TableName := GetFieldRelationName(I);
00593 ColumnLabel := GetFieldAliasName(I);
00594 ColumnType := FieldSqlType;
00595
00596 case FieldSqlType of
00597 stString,
00598 stUnicodeString: Precision := GetFieldLength(I);
00599 end;
00600
00601 ReadOnly := (GetFieldRelationName(I) = '') or (GetFieldSqlName(I) = '')
00602 or (GetFieldSqlName(I) = 'RDB$DB_KEY')
00603 or (FieldSqlType = ZDbcIntfs.stUnknown);
00604
00605 if IsNullable(I) then
00606 Nullable := ntNullable
00607 else Nullable := ntNoNulls;
00608
00609 Scale := GetFieldScale(I);
00610 AutoIncrement := False;
00611
00612
00613 end;
00614 ColumnsInfo.Add(ColumnInfo);
00615 end;
00616 inherited Open;
00617 end;
00618
00619 function TZInterbase6ResultSet.GetCursorName: string;
00620 begin
00621 Result := FCursorName;
00622 end;
00623
00624 { TZInterbase6Blob }
00625
00626 function TZInterbase6Blob.Clone: IZBlob;
00627 begin
00628 Result := TZInterbase6Blob.Create(FIBConnection, FBlobId);
00629 end;
00630
00631 {**
00632 Reads the blob information by blob handle.
00633 @param handle a Interbase6 database connect handle.
00634 @param the statement previously prepared
00635 }
00636 constructor TZInterbase6Blob.Create(IBConnection: IZInterbase6Connection;
00637 var BlobId: TISC_QUAD);
00638 begin
00639 FBlobId := BlobId;
00640 FBlobRead := False;
00641 FIBConnection := IBConnection;
00642 end;
00643
00644 function TZInterbase6Blob.GetBytes: TByteDynArray;
00645 begin
00646 ReadBlob;
00647 Result := inherited GetBytes;
00648 end;
00649
00650 function TZInterbase6Blob.GetStream: TStream;
00651 begin
00652 ReadBlob;
00653 Result := inherited GetStream;
00654 end;
00655
00656 function TZInterbase6Blob.GetString: string;
00657 begin
00658 ReadBlob;
00659 Result := inherited GetString;
00660 end;
00661
00662 function TZInterbase6Blob.GetUnicodeString: WideString;
00663 begin
00664 ReadBlob;
00665 Result := inherited GetUnicodeString;
00666 end;
00667
00668 function TZInterbase6Blob.IsEmpty: Boolean;
00669 begin
00670 ReadBlob;
00671 Result := inherited IsEmpty;
00672 end;
00673
00674 procedure TZInterbase6Blob.ReadBlob;
00675 var
00676 Size: Integer;
00677 Buffer: Pointer;
00678 begin
00679 if FBlobRead then
00680 Exit;
00681
00682 with FIBConnection do
00683 ReadBlobBufer(GetPlainDriver, GetDBHandle, GetTrHandle,
00684 FBlobId, Size, Buffer);
00685 BlobSize := Size;
00686 BlobData := Buffer;
00687 FBlobRead := True;
00688 end;
00689
00690 end.