Is the bug that stores unicode in Delphi7?
Recently, when using delphi7 to do unicode programs, I discovered such a problem, that is, when using TADOCommand component to execute SQL statements, if there are unicode characters in the SQL statement, garbled code will appear in the database, and the same is true for using TTntADOQuery (the use of parameters is not There will be garbled code, and here we will only discuss the pure SQL method). However, TADOCommand itself supports widestring, and the CommandText property is also of widestring type. Why does this problem occur? I tried to change several attribute values of TADOCommand and found a strange phenomenon. As long as the ParamCheck property is set to false, unicode characters can be stored normally, and when set to true, garbled code appears. Why does this happen? This property seems to have nothing to do with unicode itself. What exactly causes the garbled code to occur? By studying the adodb.pas file where TADOCommand is located, I found the problem. Let's take a look at the process of the bug:
PRocedure TADOCommand.AssignCommandText(const Value: WideString; Loading: Boolean);
procedure InitParameters;
var
I: Integer;
List: TParameters;
NativeCommand: string;
Begin
List := TParameters.Create(Self, TParameter);
try
NativeCommand := List.ParseSQL(Value, True);
{ Preserve existing values }
List.AssignValues(Parameters);
CommandObject.CommandText := NativeCommand;
if not Loading and (Assigned(Connection) or (ConnectionString <> '')) then
Begin
try
SetConnectionFlag(cfParameters, True);
try
{ Retrieve additional parameter info from the server if supported }
Parameters.InternalRefresh;
{ Use additional parameter info from server to initialize our list }
if Parameters.Count = List.Count then
for I := 0 to List.Count - 1 do
Begin
List[I].DataType := Parameters[I].DataType;
List[I].Size := Parameters[I].Size;
List[I].NumericScale := Parameters[I].NumericScale;
List[I].Precision := Parameters[I].Precision;
List[I].Direction := Parameters[I].Direction;
List[I].Attributes := Parameters[I].Attributes;
end
Finally
SetConnectionFlag(cfParameters, False);
end;
except
{ Ignore error if server cannot provide parameter info }
end;
if List.Count > 0 then
Parameters.Assign(List);
end;
Finally
List.Free;
end;
end;
Begin
if (CommandType = cmdText) and (Value <> '') and ParamCheck then
InitParameters
else
Begin
CommandObject.CommandText := Value;
if not Loading then Parameters.Clear;
end;
end;
Take a look at this statement:
if (CommandType = cmdText) and (Value <> '') and ParamCheck then
InitParameters
That is, when ParamCheck is true, the InitParameters process will be executed. Let's see what happens in the InitParameters process:
First, it defines a variable: NativeCommand: string; Note that it is stiffng, not widestring; let's continue to look:
NativeCommand := List.ParseSQL(Value, True);
{ Preserve existing values }
List.AssignValues(Parameters);
CommandObject.CommandText := NativeCommand;
Here, Value is of widestring type, and List.ParseSQL returns string type, and NativeCommand is also string type. In this way, a good widestring variable is placed in the string type variable, and then NativeCommand is assigned CommandObject.CommandText is given, which causes CommandObject.CommandText to not get the widesting value that should be assigned to it, which ultimately leads to the occurrence of garbled code when storing unicode.
The solution is also very simple, (if you are unwilling to modify the delphi source program) you just need to set ParamCheck to false (delphi defaults to ParamCheck to true).