![]() |
|||||||||||||||||
|
|
|||||||||||||||||
|
|
|||||||||
|
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 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: 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: 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: 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: 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: 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: 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: 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\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 default size of the text for strings that show how two objects are linked in the Data Diagram is too small. 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 the ClientDataSet thinks it does not have enough information, you see a red circle in Tree View of Data Module Designer, even after assigning ClientDataSet.Filename to a valid data set file. This is only a UI bug, the ClientDataSet functions as it should. 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\intl 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 | |||||