00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Ado Resultset common functionality }
00005 { }
00006 { Originally written by Janos Fegyverneki }
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 ZDbcAdoResultSet;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 {$IFNDEF UNIX}
00062 {$IFNDEF VER130BELOW}
00063 Types,
00064 {$ENDIF}
00065 {$ENDIF}
00066 {$IFNDEF VER130BELOW}
00067 DateUtils,
00068 {$ENDIF}
00069 Classes, SysUtils, ZClasses, ZSysUtils, ZCollections, ZDbcIntfs,
00070 ZDbcGenericResolver, ZDbcCachedResultSet, ZDbcCache, ZDbcResultSet,
00071 ZDbcResultsetMetadata, ZCompatibility, ZDbcAdo, ZPlainAdoDriver, ZPlainAdo;
00072
00073 type
00074 {** Implements Ado ResultSet. }
00075 TZAdoResultSet = class(TZAbstractResultSet)
00076 private
00077 AdoColTypeCache: TIntegerDynArray;
00078 AdoColumnCount: Integer;
00079 FFirstFetch: Boolean;
00080 protected
00081 FAdoRecordSet: ZPlainAdo.RecordSet;
00082 procedure Open; override;
00083 public
00084 constructor Create(Statement: IZStatement; SQL: string;
00085 AdoRecordSet: ZPlainAdo.RecordSet);
00086 destructor Destroy; override;
00087
00088 procedure Close; override;
00089 function Next: Boolean; override;
00090 function MoveAbsolute(Row: Integer): Boolean; override;
00091 function GetRow: Integer; override;
00092 function IsNull(ColumnIndex: Integer): Boolean; override;
00093 function GetString(ColumnIndex: Integer): string; override;
00094 function GetUnicodeString(ColumnIndex: Integer): WideString; override;
00095 function GetBoolean(ColumnIndex: Integer): Boolean; override;
00096 function GetByte(ColumnIndex: Integer): ShortInt; override;
00097 function GetShort(ColumnIndex: Integer): SmallInt; override;
00098 function GetInt(ColumnIndex: Integer): Integer; override;
00099 function GetLong(ColumnIndex: Integer): Int64; override;
00100 function GetFloat(ColumnIndex: Integer): Single; override;
00101 function GetDouble(ColumnIndex: Integer): Double; override;
00102 function GetBigDecimal(ColumnIndex: Integer): Extended; override;
00103 function GetBytes(ColumnIndex: Integer): TByteDynArray; override;
00104 function GetDate(ColumnIndex: Integer): TDateTime; override;
00105 function GetTime(ColumnIndex: Integer): TDateTime; override;
00106 function GetTimestamp(ColumnIndex: Integer): TDateTime; override;
00107 function GetBlob(ColumnIndex: Integer): IZBlob; override;
00108 end;
00109
00110 {** Implements a cached resolver with Ado specific functionality. }
00111 TZAdoCachedResolver = class (TZGenericCachedResolver, IZCachedResolver)
00112 private
00113 FHandle: ZPlainAdo.Command;
00114 FAutoColumnIndex: Integer;
00115 public
00116 constructor Create(Handle: ZPlainAdo.Connection;
00117 Statement: IZStatement; Metadata: IZResultSetMetadata);
00118
00119 procedure PostUpdates(Sender: IZCachedResultSet; UpdateType: TZRowUpdateType;
00120 OldRowAccessor, NewRowAccessor: TZRowAccessor); override;
00121 end;
00122
00123 implementation
00124
00125 uses
00126 {$IFNDEF VER130BELOW}
00127 Variants,
00128 {$ENDIF}
00129 Math, OleDB, ZMessages, ZDbcUtils, ZDbcAdoUtils;
00130
00131 {**
00132 Creates this object and assignes the main properties.
00133 @param Statement an SQL statement object.
00134 @param SQL an SQL query string.
00135 @param AdoRecordSet a ADO recordset object, the source of the ResultSet.
00136 }
00137 constructor TZAdoResultSet.Create(Statement: IZStatement; SQL: string; AdoRecordSet: ZPlainAdo.RecordSet);
00138 begin
00139 inherited Create(Statement, SQL, nil);
00140 FAdoRecordSet := AdoRecordSet;
00141 Open;
00142 end;
00143
00144 {**
00145 Destroys this object and cleanups the memory.
00146 }
00147 destructor TZAdoResultSet.Destroy;
00148 begin
00149 Close;
00150 inherited;
00151 end;
00152
00153 {**
00154 Opens this recordset and initializes the Column information.
00155 }
00156 procedure TZAdoResultSet.Open;
00157 var
00158 OleDBRowset: IUnknown;
00159 OleDBColumnsInfo: IColumnsInfo;
00160 pcColumns: Cardinal;
00161 prgInfo, OriginalprgInfo: PDBColumnInfo;
00162 ppStringsBuffer: PWideChar;
00163 I: Integer;
00164 FieldSize: Integer;
00165 ColumnInfo: TZColumnInfo;
00166 ColName: string;
00167 ColType: Integer;
00168 HasAutoIncProp: Boolean;
00169 F: ZPlainAdo.Field20;
00170 S: string;
00171 J: Integer;
00172 begin
00173
00174 if not Assigned(FAdoRecordSet) or (FAdoRecordSet.State = adStateClosed) then
00175 raise EZSQLException.Create(SCanNotRetrieveResultSetData);
00176
00177 (FAdoRecordSet as ADORecordsetConstruction).Get_Rowset(OleDBRowset);
00178 OleDBRowset.QueryInterface(IColumnsInfo, OleDBColumnsInfo);
00179
00180 OleDBColumnsInfo.GetColumnInfo(pcColumns, prgInfo, ppStringsBuffer);
00181 OriginalprgInfo := prgInfo;
00182
00183 { Fills the column info }
00184 ColumnsInfo.Clear;
00185 AdoColumnCount := FAdoRecordSet.Fields.Count;
00186 SetLength(AdoColTypeCache, AdoColumnCount);
00187
00188 HasAutoIncProp := False;
00189 if AdoColumnCount > 0 then
00190 for I := 0 to FAdoRecordSet.Fields.Item[0].Properties.Count - 1 do
00191 if FAdoRecordSet.Fields.Item[0].Properties.Item[I].Name = 'ISAUTOINCREMENT' then
00192 begin
00193 HasAutoIncProp := True;
00194 Break;
00195 end;
00196
00197 if Assigned(prgInfo) then
00198 if prgInfo.iOrdinal = 0 then
00199 Inc(Integer(prgInfo), SizeOf(TDBColumnInfo));
00200
00201 for I := 0 to AdoColumnCount - 1 do
00202 begin
00203 ColumnInfo := TZColumnInfo.Create;
00204
00205 F := FAdoRecordSet.Fields.Item[I];
00206 ColName := F.Name;
00207 ColType := F.Type_;
00208 ColumnInfo.ColumnLabel := ColName;
00209 ColumnInfo.ColumnName := ColName;
00210 ColumnInfo.ColumnType := ConvertAdoToSqlType(ColType);
00211 if F.Type_ = adGuid then
00212 FieldSize := 38
00213 else
00214 FieldSize := F.DefinedSize;
00215 if FieldSize < 0 then
00216 FieldSize := 0;
00217 ColumnInfo.ColumnDisplaySize := FieldSize;
00218 ColumnInfo.Precision := FieldSize;
00219 ColumnInfo.Currency := ColType = adCurrency;
00220 ColumnInfo.Signed := False;
00221 S := '';
00222 for J := 0 to F.Properties.Count - 1 do
00223 S := S+F.Properties.Item[J].Name + '=' + VarToStr(F.Properties.Item[J].Value) + ', ';
00224 if HasAutoIncProp then
00225 ColumnInfo.AutoIncrement := F.Properties.Item['ISAUTOINCREMENT'].Value;
00226 if ColType in [adTinyInt, adSmallInt, adInteger, adBigInt, adCurrency, adDecimal, adDouble, adNumeric, adSingle] then
00227 ColumnInfo.Signed := True;
00228
00229 ColumnInfo.Writable := (prgInfo.dwFlags and (DBCOLUMNFLAGS_WRITE or DBCOLUMNFLAGS_WRITEUNKNOWN) <> 0) and (F.Properties.Item['BASECOLUMNNAME'].Value <> null) and not ColumnInfo.AutoIncrement;
00230 ColumnInfo.ReadOnly := (prgInfo.dwFlags and (DBCOLUMNFLAGS_WRITE or DBCOLUMNFLAGS_WRITEUNKNOWN) = 0) or ColumnInfo.AutoIncrement;
00231 ColumnInfo.Searchable := (prgInfo.dwFlags and DBCOLUMNFLAGS_ISLONG) = 0;
00232 if (prgInfo.dwFlags and DBCOLUMNFLAGS_ISLONG) <> 0 then
00233 case ColumnInfo.ColumnType of
00234 stString: ColumnInfo.ColumnType := stAsciiStream;
00235 stUnicodeString: ColumnInfo.ColumnType := stUnicodeStream;
00236 end;
00237
00238 ColumnsInfo.Add(ColumnInfo);
00239
00240 AdoColTypeCache[I] := ColType;
00241 Inc(Integer(prgInfo), SizeOf(TDBColumnInfo));
00242 end;
00243 if Assigned(ppStringsBuffer) then ZAdoMalloc.Free(ppStringsBuffer);
00244 if Assigned(OriginalprgInfo) then ZAdoMalloc.Free(OriginalprgInfo);
00245 FFirstFetch := True;
00246 inherited;
00247 end;
00248
00249 {**
00250 Releases this <code>ResultSet</code> object's database and
00251 ADO resources immediately instead of waiting for
00252 this to happen when it is automatically closed.
00253
00254 <P><B>Note:</B> A <code>ResultSet</code> object
00255 is automatically closed by the
00256 <code>Statement</code> object that generated it when
00257 that <code>Statement</code> object is closed,
00258 re-executed, or is used to retrieve the next result from a
00259 sequence of multiple results. A <code>ResultSet</code> object
00260 is also automatically closed when it is garbage collected.
00261 }
00262 procedure TZAdoResultSet.Close;
00263 begin
00264 FAdoRecordSet := nil;
00265 inherited;
00266 end;
00267
00268 {**
00269 Moves the cursor down one row from its current position.
00270 A <code>ResultSet</code> cursor is initially positioned
00271 before the first row; the first call to the method
00272 <code>next</code> makes the first row the current row; the
00273 second call makes the second row the current row, and so on.
00274
00275 <P>If an input stream is open for the current row, a call
00276 to the method <code>next</code> will
00277 implicitly close it. A <code>ResultSet</code> object's
00278 warning chain is cleared when a new row is read.
00279
00280 @return <code>true</code> if the new current row is valid;
00281 <code>false</code> if there are no more rows
00282 }
00283 function TZAdoResultSet.Next: Boolean;
00284 begin
00285 Result := False;
00286 if FAdoRecordSet.BOF and FAdoRecordSet.EOF then
00287 Exit;
00288 if FAdoRecordSet.BOF then
00289 FAdoRecordSet.MoveFirst
00290 else
00291 if not FAdoRecordSet.EOF and not FFirstFetch then
00292 FAdoRecordSet.MoveNext;
00293 FFirstFetch := False;
00294 Result := not FAdoRecordSet.EOF;
00295 end;
00296
00297 {**
00298 Moves the cursor to the given row number in
00299 this <code>ResultSet</code> object.
00300
00301 <p>If the row number is positive, the cursor moves to
00302 the given row number with respect to the
00303 beginning of the result set. The first row is row 1, the second
00304 is row 2, and so on.
00305
00306 <p>If the given row number is negative, the cursor moves to
00307 an absolute row position with respect to
00308 the end of the result set. For example, calling the method
00309 <code>absolute(-1)</code> positions the
00310 cursor on the last row; calling the method <code>absolute(-2)</code>
00311 moves the cursor to the next-to-last row, and so on.
00312
00313 <p>An attempt to position the cursor beyond the first/last row in
00314 the result set leaves the cursor before the first row or after
00315 the last row.
00316
00317 <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
00318 as calling <code>first()</code>. Calling <code>absolute(-1)</code>
00319 is the same as calling <code>last()</code>.
00320
00321 @return <code>true</code> if the cursor is on the result set;
00322 <code>false</code> otherwise
00323 }
00324 function TZAdoResultSet.MoveAbsolute(Row: Integer): Boolean;
00325 begin
00326 if FAdoRecordSet.EOF or FAdoRecordSet.BOF then FAdoRecordSet.MoveFirst;
00327 if Row > 0 then
00328 FAdoRecordSet.Move(Row - 1, adBookmarkFirst)
00329 else
00330 FAdoRecordSet.Move(Abs(Row) - 1, adBookmarkLast);
00331 Result := not (FAdoRecordSet.EOF or FAdoRecordSet.BOF);
00332 end;
00333
00334 {**
00335 Retrieves the current row number. The first row is number 1, the
00336 second number 2, and so on.
00337 @return the current row number; <code>0</code> if there is no current row
00338 }
00339 function TZAdoResultSet.GetRow: Integer;
00340 begin
00341 if FAdoRecordSet.EOF or FAdoRecordSet.BOF then
00342 Result := -1
00343 else
00344 Result := FAdoRecordSet.AbsolutePosition;
00345 end;
00346
00347 {**
00348 Indicates if the value of the designated column in the current row
00349 of this <code>ResultSet</code> object is Null.
00350
00351 @param columnIndex the first column is 1, the second is 2, ...
00352 @return if the value is SQL <code>NULL</code>, the
00353 value returned is <code>true</code>. <code>false</code> otherwise.
00354 }
00355 function TZAdoResultSet.IsNull(ColumnIndex: Integer): Boolean;
00356 begin
00357 Result := VarIsNull(FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value) or
00358 VarIsEmpty(FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value);
00359 end;
00360
00361 {**
00362 Gets the value of the designated column in the current row
00363 of this <code>ResultSet</code> object as
00364 a <code>String</code> in the Java programming language.
00365
00366 @param columnIndex the first column is 1, the second is 2, ...
00367 @return the column value; if the value is SQL <code>NULL</code>, the
00368 value returned is <code>null</code>
00369 }
00370 function TZAdoResultSet.GetString(ColumnIndex: Integer): string;
00371 var
00372 NL: Integer;
00373 begin
00374 Result := '';
00375 LastWasNull := IsNull(ColumnIndex);
00376 if LastWasNull then Exit;
00377 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00378 NL := Length(Result);
00379 while (NL > 0) and (Result[NL] = ' ') do Dec(NL);
00380 SetLength(Result, NL);
00381 end;
00382
00383 {**
00384 Gets the value of the designated column in the current row
00385 of this <code>ResultSet</code> object as
00386 a <code>WideString</code> in the Delphi programming language.
00387
00388 @param columnIndex the first column is 1, the second is 2, ...
00389 @return the column value; if the value is SQL <code>NULL</code>, the
00390 value returned is <code>null</code>
00391 }
00392 function TZAdoResultSet.GetUnicodeString(ColumnIndex: Integer): WideString;
00393 var
00394 NL: Integer;
00395 begin
00396 Result := '';
00397 LastWasNull := IsNull(ColumnIndex);
00398 if LastWasNull then Exit;
00399 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00400 NL := Length(Result);
00401 while (NL > 0) and (Result[NL] = ' ') do Dec(NL);
00402 SetLength(Result, NL);
00403 end;
00404
00405 {**
00406 Gets the value of the designated column in the current row
00407 of this <code>ResultSet</code> object as
00408 a <code>boolean</code> in the Java programming language.
00409
00410 @param columnIndex the first column is 1, the second is 2, ...
00411 @return the column value; if the value is SQL <code>NULL</code>, the
00412 value returned is <code>false</code>
00413 }
00414 function TZAdoResultSet.GetBoolean(ColumnIndex: Integer): Boolean;
00415 begin
00416 Result := False;
00417 LastWasNull := IsNull(ColumnIndex);
00418 if LastWasNull then Exit;
00419 try
00420 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00421 except
00422 Result := False;
00423 end;
00424 end;
00425
00426 {**
00427 Gets the value of the designated column in the current row
00428 of this <code>ResultSet</code> object as
00429 a <code>byte</code> in the Java programming language.
00430
00431 @param columnIndex the first column is 1, the second is 2, ...
00432 @return the column value; if the value is SQL <code>NULL</code>, the
00433 value returned is <code>0</code>
00434 }
00435 function TZAdoResultSet.GetByte(ColumnIndex: Integer): ShortInt;
00436 begin
00437 Result := 0;
00438 LastWasNull := IsNull(ColumnIndex);
00439 if LastWasNull then Exit;
00440 try
00441 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00442 except
00443 Result := 0;
00444 end;
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>short</code> 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>0</code>
00455 }
00456 function TZAdoResultSet.GetShort(ColumnIndex: Integer): SmallInt;
00457 begin
00458 Result := 0;
00459 LastWasNull := IsNull(ColumnIndex);
00460 if LastWasNull then Exit;
00461 try
00462 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00463 except
00464 Result := 0;
00465 end;
00466 end;
00467
00468 {**
00469 Gets the value of the designated column in the current row
00470 of this <code>ResultSet</code> object as
00471 an <code>int</code> in the Java programming language.
00472
00473 @param columnIndex the first column is 1, the second is 2, ...
00474 @return the column value; if the value is SQL <code>NULL</code>, the
00475 value returned is <code>0</code>
00476 }
00477 function TZAdoResultSet.GetInt(ColumnIndex: Integer): Integer;
00478 begin
00479 Result := 0;
00480 LastWasNull := IsNull(ColumnIndex);
00481 if LastWasNull then Exit;
00482 try
00483 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00484 except
00485 Result := 0;
00486 end;
00487 end;
00488
00489 {**
00490 Gets the value of the designated column in the current row
00491 of this <code>ResultSet</code> object as
00492 a <code>long</code> in the Java programming language.
00493
00494 @param columnIndex the first column is 1, the second is 2, ...
00495 @return the column value; if the value is SQL <code>NULL</code>, the
00496 value returned is <code>0</code>
00497 }
00498 function TZAdoResultSet.GetLong(ColumnIndex: Integer): Int64;
00499 begin
00500 Result := 0;
00501 LastWasNull := IsNull(ColumnIndex);
00502 if LastWasNull then Exit;
00503 try
00504 {$IFDEF VER130BELOW}
00505 Result := Integer(FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value);
00506 {$ELSE}
00507 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00508 {$ENDIF}
00509 except
00510 Result := 0;
00511 end;
00512 end;
00513
00514 {**
00515 Gets the value of the designated column in the current row
00516 of this <code>ResultSet</code> object as
00517 a <code>float</code> in the Java programming language.
00518
00519 @param columnIndex the first column is 1, the second is 2, ...
00520 @return the column value; if the value is SQL <code>NULL</code>, the
00521 value returned is <code>0</code>
00522 }
00523 function TZAdoResultSet.GetFloat(ColumnIndex: Integer): Single;
00524 begin
00525 Result := 0;
00526 LastWasNull := IsNull(ColumnIndex);
00527 if LastWasNull then Exit;
00528 try
00529 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00530 except
00531 Result := 0;
00532 end;
00533 end;
00534
00535 {**
00536 Gets the value of the designated column in the current row
00537 of this <code>ResultSet</code> object as
00538 a <code>double</code> in the Java programming language.
00539
00540 @param columnIndex the first column is 1, the second is 2, ...
00541 @return the column value; if the value is SQL <code>NULL</code>, the
00542 value returned is <code>0</code>
00543 }
00544 function TZAdoResultSet.GetDouble(ColumnIndex: Integer): Double;
00545 begin
00546 Result := 0;
00547 LastWasNull := IsNull(ColumnIndex);
00548 if LastWasNull then Exit;
00549 try
00550 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00551 except
00552 Result := 0;
00553 end;
00554 end;
00555
00556 {**
00557 Gets the value of the designated column in the current row
00558 of this <code>ResultSet</code> object as
00559 a <code>java.sql.BigDecimal</code> in the Java programming language.
00560
00561 @param columnIndex the first column is 1, the second is 2, ...
00562 @param scale the number of digits to the right of the decimal point
00563 @return the column value; if the value is SQL <code>NULL</code>, the
00564 value returned is <code>null</code>
00565 }
00566 function TZAdoResultSet.GetBigDecimal(ColumnIndex: Integer): Extended;
00567 begin
00568 Result := 0;
00569 LastWasNull := IsNull(ColumnIndex);
00570 if LastWasNull then Exit;
00571 try
00572 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00573 except
00574 Result := 0;
00575 end;
00576 end;
00577
00578 {**
00579 Gets the value of the designated column in the current row
00580 of this <code>ResultSet</code> object as
00581 a <code>byte</code> array in the Java programming language.
00582 The bytes represent the raw values returned by the driver.
00583
00584 @param columnIndex the first column is 1, the second is 2, ...
00585 @return the column value; if the value is SQL <code>NULL</code>, the
00586 value returned is <code>null</code>
00587 }
00588 function TZAdoResultSet.GetBytes(ColumnIndex: Integer): TByteDynArray;
00589 begin
00590 SetLength(Result, 0);
00591 LastWasNull := IsNull(ColumnIndex);
00592 if LastWasNull then Exit;
00593 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00594 end;
00595
00596 {**
00597 Gets the value of the designated column in the current row
00598 of this <code>ResultSet</code> object as
00599 a <code>java.sql.Date</code> object in the Java programming language.
00600
00601 @param columnIndex the first column is 1, the second is 2, ...
00602 @return the column value; if the value is SQL <code>NULL</code>, the
00603 value returned is <code>null</code>
00604 }
00605 function TZAdoResultSet.GetDate(ColumnIndex: Integer): TDateTime;
00606 begin
00607 Result := 0;
00608 LastWasNull := IsNull(ColumnIndex);
00609 if LastWasNull then Exit;
00610 try
00611 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00612 except
00613 Result := 0;
00614 end;
00615 end;
00616
00617 {**
00618 Gets the value of the designated column in the current row
00619 of this <code>ResultSet</code> object as
00620 a <code>java.sql.Time</code> object in the Java programming language.
00621
00622 @param columnIndex the first column is 1, the second is 2, ...
00623 @return the column value; if the value is SQL <code>NULL</code>, the
00624 value returned is <code>null</code>
00625 }
00626 function TZAdoResultSet.GetTime(ColumnIndex: Integer): TDateTime;
00627 begin
00628 Result := 0;
00629 LastWasNull := IsNull(ColumnIndex);
00630 if LastWasNull then Exit;
00631 try
00632 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00633 except
00634 Result := 0;
00635 end;
00636 end;
00637
00638 {**
00639 Gets the value of the designated column in the current row
00640 of this <code>ResultSet</code> object as
00641 a <code>java.sql.Timestamp</code> object in the Java programming language.
00642
00643 @param columnIndex the first column is 1, the second is 2, ...
00644 @return the column value; if the value is SQL <code>NULL</code>, the
00645 value returned is <code>null</code>
00646 @exception SQLException if a database access error occurs
00647 }
00648 function TZAdoResultSet.GetTimestamp(ColumnIndex: Integer): TDateTime;
00649 begin
00650 Result := 0;
00651 LastWasNull := IsNull(ColumnIndex);
00652 if LastWasNull then Exit;
00653 try
00654 Result := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00655 except
00656 Result := 0;
00657 end;
00658 end;
00659
00660 {**
00661 Returns the value of the designated column in the current row
00662 of this <code>ResultSet</code> object as a <code>Blob</code> object
00663 in the Java programming language.
00664
00665 @param ColumnIndex the first column is 1, the second is 2, ...
00666 @return a <code>Blob</code> object representing the SQL <code>BLOB</code> value in
00667 the specified column
00668 }
00669 function TZAdoResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
00670 var
00671 V: Variant;
00672 P: Pointer;
00673 begin
00674 Result := nil;
00675 LastWasNull := IsNull(ColumnIndex);
00676 if LastWasNull then Exit;
00677
00678 V := FAdoRecordSet.Fields.Item[ColumnIndex - 1].Value;
00679 if VarIsStr(V) then
00680 begin
00681 Result := TZAbstractBlob.CreateWithStream(nil);
00682 Result.SetString(V);
00683 end;
00684 if VarIsArray(V) then
00685 begin
00686 P := VarArrayLock(V);
00687 try
00688 Result := TZAbstractBlob.CreateWithData(P, VarArrayHighBound(V, 1)+1);
00689 finally
00690 VarArrayUnLock(V);
00691 end;
00692 end;
00693 end;
00694
00695
00696 { TZAdoCachedResolver }
00697
00698 {**
00699 Creates a Ado specific cached resolver object.
00700 @param PlainDriver a native Ado plain driver.
00701 @param Handle a Ado specific query handle.
00702 @param Statement a related SQL statement object.
00703 @param Metadata a resultset metadata reference.
00704 }
00705 constructor TZAdoCachedResolver.Create(Handle: ZPlainAdo.Connection;
00706 Statement: IZStatement; Metadata: IZResultSetMetadata);
00707 var
00708 I: Integer;
00709 begin
00710 inherited Create(Statement, Metadata);
00711 FHandle := ZPlainAdo.CoCommand.Create;
00712 FHandle._Set_ActiveConnection(Handle);
00713 FHandle.CommandText := 'SELECT @@IDENTITY';
00714 FHandle.CommandType := adCmdText;
00715
00716 { Defines an index of autoincrement field. }
00717 FAutoColumnIndex := 0;
00718 for I := 1 to Metadata.GetColumnCount do
00719 begin
00720 if Metadata.IsAutoIncrement(I) and
00721 (Metadata.GetColumnType(I) in [stByte, stShort, stInteger, stLong]) then
00722 begin
00723 FAutoColumnIndex := I;
00724 Break;
00725 end;
00726 end;
00727 end;
00728
00729 {**
00730 Posts updates to database.
00731 @param Sender a cached result set object.
00732 @param UpdateType a type of updates.
00733 @param OldRowAccessor an accessor object to old column values.
00734 @param NewRowAccessor an accessor object to new column values.
00735 }
00736 procedure TZAdoCachedResolver.PostUpdates(Sender: IZCachedResultSet;
00737 UpdateType: TZRowUpdateType; OldRowAccessor, NewRowAccessor: TZRowAccessor);
00738 var
00739 Recordset: ZPlainAdo.Recordset;
00740 RA: OleVariant;
00741 begin
00742 inherited PostUpdates(Sender, UpdateType, OldRowAccessor, NewRowAccessor);
00743
00744 if (UpdateType = utInserted) and (FAutoColumnIndex > 0)
00745 and OldRowAccessor.IsNull(FAutoColumnIndex) then
00746 begin
00747 Recordset := FHandle.Execute(RA, null, 0);
00748 if Recordset.RecordCount > 0 then
00749 {$IFNDEF VER130BELOW}
00750 NewRowAccessor.SetLong(FAutoColumnIndex, Recordset.Fields.Item[0].Value);
00751 {$ELSE}
00752 NewRowAccessor.SetLong(FAutoColumnIndex,
00753 Integer(Recordset.Fields.Item[0].Value));
00754 {$ENDIF}
00755 end;
00756 end;
00757
00758 end.
00759