![]() |
|||||||||||||||||
|
|
|||||||||||||||||
|
|
|||||||||
|
Delphi |
DELPHI DEVELOPER SUPPORT
Areas of concentration under: database
Area: database Problem: SQL Explorer has errors when viewing the 'Text' definition of some items w/ a Sybase 11.9.2 database. I'm not sure if its a problem with 11.9.2 or a problem w/ Sybase in general. Note: I believe this problem is gone if you change a line in dbx.dbi described in Delphi readme file under Sybase section. Workaround: Edit DBX.DBI with a text editor (such as NotePad). DBX.DBI is located in the directory in which SQL Explorer was installed. Change the line: SYBASE:IdentityRE=SQL Server/([0-9]+)\. to: SYBASE:IdentityRE=[SQL Server][Adaptive Server Enterprise]/([0-9]+)\. Area: database\ado Problem: When saving a form with an active TADOConnection that is configured to use a datalink file, the connection string from the datalink file is saved instead of the connection string pointing to the datalink file. Workaround: Close the TADOConnection before saving. Area: database\ado Problem: Master/Detail Midas using ADO - When inserting a new detail record, the linking data is not automatically inserted into the detail field. Workaround: Write code to assign the values in the OnNewRecord event of the detail dataset. Area: database\ado Problem: When an ADO dataset has an OnFilterRecord event and a new row is inserted at the end of the dataset, an EOLEException occurs. Workaround:
Replace this method in ADODB.PAS:
function TCustomADODataSet.GetRecord(Buffer:
PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult;
var
Accept: Boolean;
SaveState: TDataSetState;
begin
if (BookmarkSize = 0) and (BufferCount > 1) then
DatabaseError(SBookmarksRequired);
if Filtered and Assigned(OnFilterRecord) then
begin
FFilterBuffer := Buffer;
SaveState := SetTempState(dsFilter);
try
Accept := True;
repeat
Result := InternalGetRecord(Buffer, GetMode,
DoCheck);
if Result = grOK then
begin
OnFilterRecord(Self, Accept);
if not Accept and (GetMode = gmCurrent)
then
Result := grError;
end;
until Accept or (Result < > grOK);
except
Application.HandleException(Self);
Result := grError;
end;
RestoreState(SaveState);
end else
Result := InternalGetRecord(Buffer, GetMode,
DoCheck)
end;
Area: database\ado Problem: TADOConnection.GetTableNames does not list views along with the table names. Workaround: Use OpenSchema method instead. Area: database\ado Problem: In ADO datasets, garbage values may be displayed in lookup fields when columns are resized or reordered, or when new records are inserted. Workaround: Requires VCL code changes. Install Update Pack. Area: database\ado Problem: When a DBGrid is connected to a ado dataset with the cursorlocation set to clUseServer, all records end up being fetched up front by the call to RecordCount. Workaround: Use client side cursor or Turn off the vertical scrollbar in the grid. Area: database\ado Problem: In a Master/Detail setup using two TADOTable components if the detail table is closed, then opened again the filter is lost, and the whole table is displayed. Workaround: Use a query instead of a table for the detail. Area: database\ado Problem: Parameterized INSERT or UPDATE queries may cause VARCHAR fields to be stored with trailing spaces. Primarily occurs updating through Midas. Workaround: If using SQL Server, modify the table so that it is created with ANSI_PADDING set to OFF. Area: database\ado Problem: When the master dataset contains no records (because it is filtered), all records are displayed from the detail dataset instead of no records. Workaround: Use a query instead of a table for the detail. Area: database\ado Problem: CancelBatch does not cancel Edit mode. Workaround: Call Cancel before calling CancelBatch. Area: database\ado Problem: TADODataSet.CancelUpdates does not work as documented. It should do the same thing as CancelBatch. Workaround: Call Cancel & CancelBatch instead. Area: database\ado Problem: Calling ClearFields on an ADO dataset results in an invalid variant exception. Workaround: Use a for loop and clear the fields individually instead. Area: database\ado Problem: After deleting all records in a dataset, then calling CancelBatch to restore them, no data is displayed. Workaround:
Replace this method in ADODB.PAS:
procedure
TCustomADODataSet.CancelBatch(AffectRecords:
TAffectRecords);
begin
Cancel;
UpdateCursorPos;
Recordset.CancelBatch(AffectRecordsValues[Affec
tRecords]);
{ If all records were previously deleted, ADO does
not reset EOF flag }
if Recordset.EOF and RecordSet.BOF and
(Recordset.RecordCount > 0) then
Recordset.MoveFirst else
UpdateCursorPos;
Resync([]);
end;
Area: database\ado Problem: Scrolling through an ADO dataset with CursorLocation = cllUseClient is significantly slower than the equivalent operation usiing straight ADO. Problem is the call to Recordset.AbsolutePosition which is made in the InternalGetRecord method call. Workaround: Use a server side cursor instead. Area: database\ado Problem: Calling Clear on a TBlobField in an ADO dataset does not clear the field. Workaround: Assign a Null value directly to the underlying recordset and then call resync. ADODataSet1.UpdateCursorPos; ADODataSet1.Recordset.Fields['BlobField'].Value := Null; ADODataSet1.Recordset.Update(EmptyParam, EmptyParam); ADODataSet1.Resync([]); Area: database\ado Problem: Using the LoadFromFile method on an ADO dataset fails with an exception when there is no associated Connection component or ConnectionString. Workaround: Associate a connection component. Area: database\ado Problem: When using Lookup fields, inserting a record will generate "An unknown error has occured" exception in some cases. Workaround: Requires VCL code changes. Install Update Pack. Area: database\ado Problem: An AV occurs when writing to the ParamValues property of TParameters with multiple values. Workaround: Use Value property instead. Area: database\ado Problem: Callling the AppendRecord or InsertRecord methods after closing and reopening the dataset may cause an Access Violation. Workaround: Call Edit then Cancel in the AfterOpen event of the dataset. Area: database\ado Problem: Calling the AppendRecord methods with a grid attached to an empty dataset may result in an invalid parameter exception. Workaround: Use Insert or InsertRecord instead. Area: database\ado Problem: An infinite loop may result if using the OnFilterRecord event and returning Accept = False from the event. Workaround: Use a filter string instead if possible. Area: database\ado Problem: In Midas, when providing from ADO datasets using non-nested master/detail, it is possible to receive a "Key violation" error when you scroll to a master record that has no detail records. Workaround: Use nested master/detail instead. Area: database\ado Problem: TADODataset does not trim trailing spaces on CHAR field types (neither does ADO itself). Workaround: Use a VARCHAR field instead. Area: database\ado Problem: Issuing an Update or Delete statement prior to a Select in a Stored Procedure results in "CommandText does not return a result set". Same error occurs when executing a stored procedure that returns warnings. Workaround:
Issue the command the using a TADOCommand
object and call the NextRecordset method on the
returned recordset until the state is open then
assign the recordset object to a TADODataSet
component. For example:
var
RS: _Recordset;
begin
RS := ADOCommand1.Exeute;
while RS.State = adStateClosed do
RS := RS.NextRecordset;
ADODataSet1.Recordset := RS;
end;
or replace this code in ADODB.PAS:
procedure
TCustomADODataSet.OpenCursor(InfoQuery:
Boolean);
const
AsyncOptions = [eoAsyncExecute, eoAsyncFetch,
eoAsyncFetchNonBlocking];
var
ActiveConnection,
Source: OleVariant;
procedure InitializeConnection;
var
UseCommand: Boolean;
begin
{ Async operations require a connection
component so we can hook events }
if not Assigned(Connection) and (ExecuteOptions
* AsyncOptions < > []) then
DatabaseError(SConnectionRequired);
FConnectionChanged := False;
ActiveConnection := EmptyParam;
UseCommand := not (CommandType in
RSOnlyCommandTypes);
if UseCommand then
begin
SetConnectionFlag(cfOpen, True);
Command.Initialize;
InitializeMasterFields(Self);
Source := Command.CommandObject;
end else
begin
{ Can't use command for cmdFile and
cmdTableDirect }
if Assigned(Connection) then
begin
Connection.Open;
ActiveConnection :=
Connection.ConnectionObject;
end else if ConnectionString < > '' then
ActiveConnection := ConnectionString;
Command.CheckCommandText;
Source := CommandText;
end;
end;
procedure InitializeRecordset;
begin
FRecordsetObject :=
CreateADOObject(CLASS_Recordset) as
_Recordset;
Recordset.CursorLocation :=
CursorLocationValues[FCursorLocation];
Recordset.CacheSize := FCacheSize;
Recordset.MaxRecords := FMaxRecords;
if FIndexName < > '' then
begin
Recordset.Index := FIndexName;
RefreshIndexFields;
end;
EnableEvents;
end;
var
VarRecsAffected: OleVariant;
begin
if not Assigned(Recordset) then
begin
InitializeConnection;
InitializeRecordset;
Recordset.Open(Source, ActiveConnection,
CursorTypeValues[FCursorType],
LockTypeValues[FLockType],
CommandTypeValues[CommandType] +
ExecuteOptionsToOrd(ExecuteOptions));
while Recordset.State = adStateClosed do
try
FRecordsetObject :=
Recordset.NextRecordset(VarRecsAffected);
if Recordset = nil then Abort;
except
DatabaseError(SNoResultSet, Self);
end;
end else
EnableEvents;
if (eoAsyncExecute in ExecuteOptions) and
((Recordset.State and adStateExecuting) < > 0)
then
SetState(dsOpening);
inherited OpenCursor(False);
end;
Area: database\ado Problem: When the IndexName property is set, the IndexFieldCount and IndexFields properties are not updated. (Note that ADO only supports the Recordset.Index property for the Jet provider using an Access database). Workaround:
Use the IndexDef information instead.
For example:
var
IndexDef: TIndexDef;
FList: string;
begin
if Active and (IndexName < > '') then
begin
IndexDefs.Update;
IndexDef := IndexDefs.Find(IndexName);
if IndexDef < > nil then
FList := IndexDef.Fields else
FList := '';
end else
Area: database\ado Problem: IndexName has no effect when an index is selected. Workaround: This is a provider limitation. To use the IndexName property you must use the Jet 4.0 provider with an Access 2000 format database. In addition you must set CursorLocation = clUseServer and CommandType = cmdTableDirect. Area: database\ado Problem: Calling the seek method on an empty dataset results in an EOLEException saying there is no current record. Workaround: Check the IsEmpty property before calling Seek. Area: database\ado Problem: When posting a record from a disconnected (RDS) dataset, garbage values will display in required fields that are not initialized. Workaround: Set the required property to True on fields which are required on the source dataset. Area: database\ado Problem: If you set any field to read-only in the OnAfterInsert method then the new record just inserted gets filled in with the values of the record you were just on. Workaround: Set the ReadOnly property in a different place such as the OnNewRecord event. Area: database\ado Problem: When using an ADO dataset with MIDAS under MTS a missing connection error is generated when applying updates if the connection is closed. Workaround: Open the connection in code in the BeforeUpdateRecords event. Area: database\ado Problem: After attempting to delete a record which causes an error, subsequent attempts to scroll through the dataset will result in additonal invalid errors. [Also verified in BCB5, 5.0.12.14] Workaround: In the OnDeleteError event add this code: ADODataSet1.RecordSet.CancelUpdates; Area: database\ado Problem: There is no way to set the CommandTimeout property when using TADOQuery, TADOTable, and TADOStoredProc. Area: database\ado Problem: When assigning a TParam with a null value to a TParameter the datatype is not set, resulting in an invalid parameter error when executing the command. This affects Midas applications when calling ApplyUpdates after setting a field to null. Workaround: Requires VCL code changes. Install Update Pack. Area: database\ado Problem: ADO and ODBC InterSolv InterBase Driver - Attempting to edit a record that has a ftString field filled results in "Errors occurred". Workaround: None. This is a limitation of the Intersolv (Merant) ODBC driver. Area: database\ado Problem: The ftDate, ftTime and ftDateTime field types are being mapped to the wrong ADO types when used with parameters. They should all be mapped to adDate. [Also verified code change in BCB5, 5.0.12.14] Workaround:
Replace this const in ADODB.PAS:
DataTypeValues: array[TDataType] of TOleEnum
= (
adEmpty, adVarChar, adSmallint, adInteger,
adUnsignedSmallint,
adBoolean, adDouble, adDouble, adCurrency,
adDate, adDate,
adDate, adBinary, adVarBinary, adInteger,
adLongVarBinary,
adLongVarChar, adLongVarBinary,
adLongVarBinary, adLongVarBinary,
adLongVarBinary, adLongVarBinary, adEmpty,
adChar, adChar, adBigInt,
adEmpty, adEmpty, adEmpty, adEmpty, adEmpty,
adEmpty, adVariant,
adIUnknown, adIDispatch, adGuid
);
Area: database\ado Problem: When inserting a new master record, all detail records are displayed. [Also verified in BCB5, 5.0.12.16 but used the bcb attachment] Workaround: Requires VCL code changes. Install Update Pack. Area: database\ado Problem: Currently, pessimistic record locking does not work with the ADO components because ADO doesn't provide a way to lock a record other than the current record. Area: database\ado Problem: Attempting to navigate to the last record after previously deleting the last record result in the error: 'Either BOF or EOF is true, or the current record has been deleted; the operation requested by the application requires a current record'. Provider = SQLOLEDB, CursorLocation = clUseServer, CursorType = ctKeyset. Workaround: This is a bug in the SQL Server provider. Set CursorLocation = clUseClient to eliminate the error. Area: database\ado Problem: The ADO field type adDate should be mapped to ftDateTime and use a TDateTimeField since this data time can also contain time information. [Also verified in BCB5, 5.0.12.14] Workaround:
Use a persistent field object of type TDateTimeField
or modify this routine in ADODB.PAS:
function ADOTypeToFieldType(const ADOType:
DataTypeEnum; EnableBCD: Boolean = True):
TFieldType;
begin
case ADOType of
adEmpty: Result := ftUnknown;
adTinyInt, adSmallInt: Result := ftSmallint;
adError, adInteger, adUnsignedInt: Result :=
ftInteger;
adBigInt, adUnsignedBigInt: Result := ftLargeInt;
adUnsignedTinyInt, adUnsignedSmallInt: Result
:= ftWord;
adSingle, adDouble: Result := ftFloat;
adCurrency: Result := ftBCD;
adBoolean: Result := ftBoolean;
adDBDate: Result := ftDate;
adDBTime: Result := ftTime;
adDate, adDBTimeStamp, adFileTime,
adDBFileTime: Result := ftDateTime;
adChar: Result := ftFixedChar;
adVarChar: Result := ftString;
adBSTR, adWChar, adVarWChar: Result :=
ftWideString;
adLongVarChar, adLongVarWChar: Result :=
ftMemo;
adLongVarBinary: Result := ftBlob;
adBinary: Result := ftBytes;
adVarBinary: Result := ftVarBytes;
adChapter: Result := ftDataSet;
adPropVariant, adVariant: Result := ftVariant;
adIUnknown: Result := ftInterface;
adIDispatch: Result := ftIDispatch;
adGUID: Result := ftGUID;
adDecimal, adNumeric, adVarNumeric:
if EnableBCD then Result := ftBCD
else Result := ftFloat;
else
Result := ftUnknown;
end;
end;
Area: database\ado Problem: CancelBatch(arCurrent) may fail or cancel updates for the wrong record if the ADO Recordset's cursor is not currently synchronized with the Dataset's cursor position. [Also verified in BCB5, 5.0.12.16] Workaround: Call UpdateCursorPos on the dataset prior to calling the CancelBatch. Area: database\ado Problem: When using a datasource for parameter binding, the corresponding parameter values are not set when using ExecSQL or Execute to run the command. [Also verified in BCB5, 5.0.12.16] Workaround: Call Open inside of a try/except block instead of calling ExecSQL. An error will be raised about no result set, but that can be ignored in the except handler. Area: database\ado Problem: If you use connection events and reassign the ConnectionObject the events will stop working. Area: database\ado Problem: When doing a locate on an empty string value with loPartialKey specified an invalid parameter error is raised. Workaround:
Instead of passing an empty string ('') to the Locate
method, pass a Null variant.
Area: database\ado Problem: Sorting a field with spaces in the field name will cause an exception to be raised. Workaround:
Replace this method in ADODB.PAS:
procedure
TCustomADODataSet.RefreshIndexFields;
var
IndexDef: TIndexDef;
FList: string;
begin
if Active and (IndexName < > '') then
begin
IndexDefs.Update;
IndexDef := IndexDefs.Find(IndexName);
if IndexDef < > nil then
FList := IndexDef.Fields else
FList := '';
end else
begin
FList := StringReplace(Sort, ',', ';', [rfReplaceAll]);
FList := StringReplace(FList, ' DESC', '',
[rfReplaceAll]);
FList := StringReplace(FList, ' ASC', '',
[rfReplaceAll]);
FList := StringReplace(FList, '[', '', [rfReplaceAll]);
FList := StringReplace(FList, ']', '', [rfReplaceAll]);
end;
FIndexFields.Clear;
GetFieldList(FIndexFields, FList);
end;
Area: database\ado Problem: Assigning a closed recordset object to a TADODataset can cause a stack overflow error. Workaround: Make sure any recordset objects are open before assigning them to the Recordset property of TADODataset. Area: database\ado Problem: AV results when attempting to close a project with RDSConnection and Ado dataset. [Also verified in BCB5, 5.0.12.14] Workaround:
Change the creation order so that the RDS
Connection component is after any associated
datasets or modify the VCL as follows, note this will
not correct the problem at design time as the fix
needs to be recompiled into the VCLADO50.BPL
package.
Replace this method in ADODB.PAS:
procedure TADODataSet.SetConnection(const
Value: TADOConnection);
begin
if Assigned(Value) or (csDestroying in
ComponentState) then
RDSConnection := nil;
inherited;
end;
Area: database\ado Problem: [ODBC Provider] When assigning the CommandText of a query with parameters in code, or calling Parameters.Refresh an invalid argument exception is raised. [Also verified in BCB5, 5.0.12.16 but using ParamByName rather than Parameters] Workaround:
Use the native provider instead (SQLOLEDB).
Or replace this nested procedure in
TParameters.InternalRefresh:
procedure RefreshFromOleDB;
var
I: Integer;
ParamCount: UINT;
ParamInfo: PDBParamInfoArray;
NamesBuffer: POleStr;
Name: WideString;
Parameter: _Parameter;
Direction: ParameterDirectionEnum;
OLEDBCommand: ICommand;
OLEDBParameters: ICommandWithParameters;
CommandPrepare: ICommandPrepare;
begin
OLEDBCommand := (Command.CommandObject
as ADOCommandConstruction).OLEDBCommand
as ICommand;
OLEDBCommand.QueryInterface(ICommandWithPa
rameters, OLEDBParameters);
OLEDBParameters.SetParameterInfo(0, nil, nil);
if Assigned(OLEDBParameters) then
begin
ParamInfo := nil;
NamesBuffer := nil;
try
OLEDBCommand.QueryInterface(ICommandPrepar
e, CommandPrepare);
if Assigned(CommandPrepare) then
CommandPrepare.Prepare(0);
if
OLEDBParameters.GetParameterInfo(ParamCount,
PDBPARAMINFO(ParamInfo), @NamesBuffer) =
S_OK then
for I := 0 to ParamCount - 1 do
with ParamInfo[I] do
begin
{ When no default name, fabricate one like
ADO does }
if pwszName = nil then
Name := 'Param' + IntToStr(I+1) else { Do
not localize }
Name := pwszName;
{ ADO maps DBTYPE_BYTES to
adVarBinary }
if wType = DBTYPE_BYTES then wType
:= adVarBinary;
{ ADO maps DBTYPE_STR to adVarChar
}
if wType = DBTYPE_STR then wType :=
adVarChar;
Direction := dwFlags and $F;
{ Verify that the Direction is initialized }
if Direction = adParamUnknown then
Direction := adParamInput;
Parameter :=
Command.CommandObject.CreateParameter(Name,
wType, Direction, ulParamSize, EmptyParam);
Parameter.Precision := bPrecision;
Parameter.NumericScale :=
ParamInfo[I].bScale;
Parameter.Attributes := dwFlags and
$FFFFFFF0; { Mask out Input/Output flags }
AddParameter.FParameter := Parameter;
end;
finally
if (ParamInfo < > nil) then
GlobalMalloc.Free(ParamInfo);
if (NamesBuffer < > nil) then
GlobalMalloc.Free(NamesBuffer);
end;
end;
end;
Area: database\ado Problem: The parameters do not appear if a stored procedure contains spaces in its name. Workaround: Rename the procedure to remove the spaces from the name. Area: database\ado Problem: After obtaining a key violation and pressing < Esc > to cancel the entry, the records will disappear from the grid (but data still exists in the table). The problem occurs when inserting a record at the end of the table. I do not see the problem when inserting a key violation record in the bot or prior to the eot. Workaround:
Replace this method in ADODB.PAS:
procedure TCustomADODataSet.InternalPost;
procedure UpdateData;
var
I: Integer;
FieldData: PVariantList;
Data: OleVariant;
begin
FieldData := PVariantList(ActiveBuffer +
SizeOf(TRecInfo));
for I := 0 to FModifiedFields.Count - 1 do
with TField(FModifiedFields[I]) do
if not ReadOnly then
begin
Data := FieldData[Index];
if not VarIsEmpty(Data) then
Recordset.Fields[FieldNo-1].Value := Data;
end;
if (Recordset.EditMode * (adEditInProgress +
adEditAdd)) < > 0 then
Recordset.Update(EmptyParam, EmptyParam);
end;
procedure CheckForFlyAway;
begin
if BookmarkSize > 0 then
try
{ Check for fly away }
Recordset.Bookmark := Recordset.Bookmark;
if Recordset.EOF or Recordset.BOF then
begin
{ If recordset is empty, then this prevents an
error calling InternalFirst }
if not Recordset.BOF and
Recordset.Supports(adMovePrevious) then
Recordset.MovePrevious;
{ Reposition to last record we were on }
CursorPosChanged;
UpdateCursorPos;
end;
except
CursorPosChanged;
end;
end;
begin
UpdateCursorPos;
try
if State = dsEdit then
UpdateData
else
begin
Recordset.AddNew(EmptyParam, EmptyParam);
try
UpdateData;
except
CursorPosChanged;
Recordset.CancelUpdate;
{ *** Fix is here *** }
{ When appending recordset may be left in an
invalid state, reset it }
if Recordset.EOF and Recordset.BOF and
(Recordset.RecordCount > 0) and EOF then
Recordset.MoveLast;
raise;
end;
end;
except
on E: Exception do
DatabaseError(E.Message);
end;
CheckForFlyAway;
end;
Area: database\ado Problem: If using a lookup field and a record has been deleted from the dataset in batch update mode, then setting the FilterGroup to fgPendingRecords will raise an exception. Workaround:
Replace this method in ADODB.PAS:
function TCustomADODataSet.GetFieldData(Field:
TField; Buffer: Pointer;
NativeFormat: Boolean): Boolean;
var
RecBuf: PChar;
Data: OleVariant;
procedure CurrToBuffer(const C: Currency);
begin
if NativeFormat then
DataConvert(Field, @C, Buffer, True) else
Currency(Buffer^) := C;
end;
procedure VarToBuffer;
begin
with tagVariant(Data) do
case Field.DataType of
ftGuid, ftFixedChar, ftString:
begin
PChar(Buffer)[Field.Size] := #0;
WideCharToMultiByte(0, 0, bStrVal,
SysStringLen(bStrVal)+1,
Buffer, Field.Size, nil, nil);
end;
ftWideString:
begin
VarDataSize(Data);
WideString(Buffer^) := bStrVal;
end;
ftSmallint:
SmallInt(Buffer^) := iVal;
ftWord:
Word(Buffer^) := bVal;
ftAutoInc, ftInteger:
Integer(Buffer^) := lVal;
ftFloat, ftCurrency:
if vt = VT_R8 then
Double(Buffer^) := dblVal else
Double(Buffer^) := Data;
ftBCD:
if vt = VT_CY then
CurrToBuffer(cyVal) else
CurrToBuffer(Data);
ftBoolean:
WordBool(Buffer^) := vbool;
ftDate, ftTime, ftDateTime:
if NativeFormat then
DataConvert(Field, @date, Buffer, True)
else
TOleDate(Buffer^) := date;
ftBytes, ftVarBytes:
if NativeFormat then
DataConvert(Field, @Data, Buffer, True)
else
OleVariant(Buffer^) := Data;
ftInterface: IUnknown(Buffer^) := Data;
ftIDispatch: IDispatch(Buffer^) := Data;
ftLargeInt: LargeInt(Buffer^) :=
Decimal(Data).Lo64;
ftBlob..ftTypedBinary, ftVariant:
OleVariant(Buffer^) := Data;
else
DatabaseErrorFmt(SUsupportedFieldType,
[FieldTypeNames[Field.DataType],
Field.DisplayName]);
end;
end;
procedure RefreshBuffers;
begin
Reserved := Pointer(FieldListCheckSum(Self));
UpdateCursorPos;
Resync([]);
end;
begin
Result := GetActiveRecBuf(RecBuf);
if not Result then Exit;
if not Assigned(Reserved) then RefreshBuffers;
Data :=
PVariantList(RecBuf+SizeOf(TRecInfo))[Field.Index]
;
if VarIsEmpty(Data) and (Field.FieldNo > 0) then
begin
UpdateRecordSetPosition(RecBuf);
if (Recordset.Status and adRecDeleted) = 0 then
Data := Recordset.Fields[Field.FieldNo-1].Value;
if VarIsEmpty(Data) then Data := Null;
PVariantList(RecBuf+SizeOf(TRecInfo))[Field.Index]
:= Data;
end;
Result := not VarIsNull(Data);
if Result and (Buffer < > nil) then
VarToBuffer;
end;
Area: database\ado Problem: Binding a grid to an TADOQuery with a CursorLocation = clUseServer and Multiselect = True results in odd results when you multi-select records. Workaround:
Replace this method in ADODB.PAS:
function
TCustomADODataSet.CompareBookmarks(Bookma
rk1,
Bookmark2: TBookmark): Integer;
var
B1, B2: Integer;
const
RetCodes: array[Boolean, Boolean] of ShortInt =
((2, -1),(1, 0));
begin
Result := RetCodes[Bookmark1 = nil, Bookmark2
= nil];
if Result = 2 then
try
Result :=
RecordSet.CompareBookmarks(POleVariant(Bookm
ark1)^,
POleVariant(Bookmark2)^) - 1;
if Result > 1 then
begin
B1 := POleVariant(Bookmark1)^;
B2 := POleVariant(Bookmark2)^;
if B1 > B2 then
Result := 1 else
Result := -1;
end;
except
Result := 0;
end;
end;
Area: database\core vcl Problem: If a Delphi project contains a TDatabase component or a TIBDatabase component, and connected is true, if the Database Server cannot be loaded for some reason at runtime, an Ole exception is thrown before the correct message is returned from the server. Area: database\data access controls\tquery Problem: Persistent fields in TQuery where the SQL is a join and * is provided in the field list show an incorrect Origin property. The BDE version doesn't seem to matter. Area: database\data aware controls\tdatalink Problem: When doing Master/Detail with queries the data aware controls attached to the detail dataset may not update correctly when scrolling the master. This happens consistently with persistent fields on the detail, otherwise it is an intermittent problem. This is a regression from Delphi 4. Workaround:
Replace this method in DBCTRLS.PAS:
procedure TFieldDataLink.UpdateField;
begin
if Active and (FFieldName < > '') then
begin
FField := nil;
if Assigned(FControl) then
SetField(GetFieldProperty(DataSource.DataSet,
FControl, FFieldName)) else
SetField(DataSource.DataSet.FieldByName(FFieldN
ame));
end else
SetField(nil);
end;
Area: database\data aware controls\tdblookupcombobox Problem: IntelliMouse wheel movement puts DBLookupComboBox in an infinite loop. The application has to be killed to terminate. Th64is only occurs with the newest (2.2d) driver, 2.1 works fine. Area: database\data module\designer Problem: The Print feature in the Data Diagramm does not print any text on my HP 6P printer. I have added some tables into the diagram and the fields are displayed, but they do not print out. Also the descriptions of the connections (Master/Detail) are not printed. Only the text in the page header does print. The graphical elemnts are corectly printed. Area: database\data module\designer Problem: The MasterDetail and Lookup selections in the Data Diagram of the Data Module Designer do not display the dialog to create the link between a master and detail table. Note:// This only effects ADO. Area: database\data module\designer Problem: Shift-Delete is treated as 'Delete' instead of 'Cut' while editing text in a data diagram comment block. Other keys such as Ctrl-Insert, Shift-Insert, Alt-Backspace work fine. Workaround: press Ctrl-X instead of Shift-Delete. Area: database\data module\designer Problem: In the Data Module Designer if you drag a data access control from the tree pane to the Data Diagram pane you will get an AV in dsnide50.bpl. Area: database\international lang driver\bantam Problem: Sometimes the call to DbiNativeToAnsi function causes an AV in BANTAM.DLL when RDMs access data from multiple threads. Also affects DbiAnsiToNative Workaround:
Modify DBTables.pas as follows:
Add these global vars:
CSNativeToAnsi: TRTLCriticalSection;
CSAnsiToNative: TRTLCriticalSection;
Add this code in the initialization/finalization section:
InitializeCriticalSection(CSNativeToAnsi);
InitializeCriticalSection(CSAnsiToNative);
finalization // < = existing code...
DeleteCriticalSection(CSAnsiToNative);
DeleteCriticalSection(CSNativeToAnsi)
Replace these functions:
procedure AnsiToNativeBuf(Locale: TLocale;
Source, Dest: PChar; Len: Integer);
var
DataLoss: LongBool;
begin
if Len > 0 then
if Locale < > nil then
begin
EnterCriticalSection(CSAnsiToNative);
DbiAnsiToNative(Locale, Dest, Source, Len,
DataLoss);
LeaveCriticalSection(CSAnsiToNative);
end else
CharToOemBuff(Source, Dest, Len);
end;
procedure NativeToAnsiBuf(Locale: TLocale;
Source, Dest: PChar; Len: Integer);
var
DataLoss: LongBool;
begin
if Len > 0 then
if Locale < > nil then
begin
EnterCriticalSection(CSNativeToAnsi);
DbiNativeToAnsi(Locale, Dest, Source, Len,
DataLoss);
LeaveCriticalSection(CSNativeToAnsi);
end else
OemToCharBuff(Source, Dest, Len)
end;
;
Area: database\tfield\tbinaryfield Problem: TBinaryField.SetAsString is no longer padding the field contents with null values if the supplied string is smaller than the datasize of the field. This is a regression from Delphi 4. Workaround:
Pass a string that contins embeded null values to fill
the field completely.
or
Replace this nested procedure in DB.PAS/
TDataset.DataConvert:
procedure ByteArrayToBuffer(const Data:
OleVariant; Buffer: Pointer; var DataSize: Word);
var
PVarData: Pointer;
begin
DataSize := VarArrayHighBound(Data, 1)+1;
PVarData := VarArrayLock(Data);
try
Move(PVarData^, Buffer^, DataSize);
if DataSize < Field.DataSize then
FillChar((PChar(Buffer)+DataSize)^,
Field.DataSize - DataSize, 0);
finally
VarArrayUnlock(Data);
end;
end;
NOTE: These listings are for informational use only. It is
not intended for use when calling Borland's Developer Support Department.
If you have any suggestions or complaints about these 'Delphi Enhancements and Fixes' pages, please contact the Delphi Administrator. This e-mail address is not intended for support issues. |
|
|
|
|||||
| Made in Borland® Copyright© 1994-2003 Borland Software Corporation. All rights reserved. Report Piracy, Legal Notices, Privacy Policy | |||||