What is the Unicode storage bug in Delphi7?
Recently, when using Delphi7 for Unicode programs, we found this problem: when using the tadocommand component to execute an SQL statement, if the SQL statement contains Unicode characters, garbled characters will appear in the database, the same is true for ttntadoquery (the parameter method does not contain garbled characters. Here we only discuss the pure SQL method ). However, tadocommand supports widestring. The commandtext attribute is also of the widestring type. Why does this problem occur? I tried to change several tadocommand attribute values and found a strange phenomenon. As long as the paramcheck attribute is set to false, Unicode characters can be properly stored, and garbled characters will appear when it is set to true. Why is this happening? This attribute seems to have nothing to do with Unicode itself. What causes garbled characters? By studying the ADODB. Pas file where tadocommand is located, I found the problem. Let's take a look at the bug process:
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 = plain text) and (value <> '') and paramcheck then
Initparameters
Else
Begin
Commandobject. commandtext: = value;
If not loading then parameters. Clear;
End;
End;
Let's look at this statement:
If (commandtype = plain text) and (value <> '') and paramcheck then
Initparameters
That is, when paramcheck is true, the initparameters process is executed. Let's take a look at what happened during this initparameters process:
First, it defines a variable: nativecommand: string;. Note that stirng is not a widestring. Let's look at it:
Nativecommand: = List. parsesql (value, true );
{Preserve existing values}
List. assignvalues (parameters );
Commandobject. commandtext: = nativecommand;
Here, value is of the widestring type, and list. parsesql returns the string type, and nativecommand is also the string type. In this way, a good widestring variable is placed in the string type variable, and then nativecommand is assigned to commandobject. commandtext causes commandobject. commandtext does not get the widesting value that should be assigned to it, which leads to garbled Characters During Unicode storage.
The solution is also very simple (if you do not want to modify the Delphi source program), you only need to set paramcheck to false (Delphi sets paramcheck to true by default ).