TOraQuery: problem with € in parameter

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
MaximG
Devart Team
Posts: 1822
Joined: Mon 06 Jul 2015 11:34

Re: TOraQuery: problem with € in parameter

Post by MaximG » Wed 29 Nov 2017 11:52

We again tested the performance of ODAC 10.1.3 when using the euro symbol. The national server coding you use (WE8ISO8859P15) does not match the client encoding (ISO 8859-1). To correctly work with the euro symbol, we tested and are sure of the working capacity of the following methods:

a) use the UseUnicode option: OraSession.Options.UseUniсode: = True
b) kinding

Code: Select all

OraQuery.ParamByName ('...'). AsAnsiString: = '1 €';
c) explicitly specifying a parameter before assigning a value to it:

Code: Select all

OraQuery.ParamByName ('...'). DataType: = ftString;
OraQuery.ParamByName ('...'). AsAnsiString: = '1 €';
d) Using the global ParamStringAsAnsiString variable in the DBAccess.pas module:

Code: Select all

ParamStringAsAnsiString: = True;
You can use any of these methods. We can not affect the behavior of the following code:

Code: Select all

OraQuery.ParamByName ('...'). Value: = '1 €';
Therefore, in this case you need to explicitly convert the assigned value:

Code: Select all

OraQuery.ParamByName ('...'). Value: = AnsiString ('1 €');

Daniele Buttarelli
Posts: 56
Joined: Fri 02 Aug 2013 07:51

Re: TOraQuery: problem with € in parameter

Post by Daniele Buttarelli » Wed 29 Nov 2017 16:56

I tried to change DBAccess.pas to fix the Value problem.
I introduced these new functions:

Code: Select all

function TDAParam.IsStringDataType(DataType: TFieldType): boolean;
begin
  Result := DataType in [ftString, ftWideString];
end;
function TDAParam.IsString: boolean;
begin
  Result := IsStringDataType(DataType);
end;
I modified the TDAParam.SetAsVariant procedure in this way (see comments):

Code: Select all

procedure TDAParam.SetAsVariant(const Value: variant);
var
  i: integer;
  LowIndex, HighIndex: integer;
  AllNulls: boolean;
begin
  if VarIsArray(Value) and (VarType(Value) <> varArray or varByte) then begin
    if VarType(Value) <> varByRef or varVariant then begin
      LowIndex := VarArrayLowBound(Value, 1);
      HighIndex := VarArrayHighBound(Value, 1);
      ValueCount := HighIndex - LowIndex + 1;
      if VarType(Value) = varArray or varVariant then
        SetDataType(ftUnknown)
      else begin
        AllNulls := True;
        for i := LowIndex to HighIndex do
          if not (VarIsEmpty(Value[i]) or VarIsNull(Value[i])) then begin
            SetDataType(GetVarType(VarType(Value[i])));
            AllNulls := False;
            Break;
          end;
        if AllNulls then
          SetDataType(ftUnknown);
      end;
      for i := LowIndex to HighIndex do
        GetParamValue(i - LowIndex).Value := Value[i];
    end
    else
      Assert(TVarData(Value).VPointer = @FDataPtr);
  end
  else begin
    CheckSetValue;

    if IsBlob then begin
      Assert(ParamObject is TBlob);
      if VarType(Value) = varNull then
        TBlob(ParamObject).Clear
      else if VarType(Value) = varArray or varByte then
        TBlob(ParamObject).AsBytes := Value
      else
        TBlob(ParamObject).AsString := VarToStr(Value);
    end
    // Changes - Start
    else
    if IsString then
      inherited Value := AnsiString(Value)
    // Changes - End
    else
      inherited Value := Value;
  end;
  Bound := True;
end;
It seems to work properly.
Can you give me your opinion on these changes?
Thanks.

MaximG
Devart Team
Posts: 1822
Joined: Mon 06 Jul 2015 11:34

Re: TOraQuery: problem with € in parameter

Post by MaximG » Mon 04 Dec 2017 15:32

You can use the made changes to implement the described behavior. Note that this method cannot be applied when using codepages with Unicode.

Post Reply