#1 2015-02-26 12:46:14

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Exception and WorkAround since 1.18.958

Hi Arnoud we get a Exception in our MVC Server since your Modifikations in SynCommons Version 957 to 958.

I debugged a lot today and modified SynCommons in a way that our code works again.

procedure SetVariantByValue(const Source: Variant; var Dest: Variant);
begin
  if not(TVarData(Dest).VType in VTYPE_STATIC) then
    VarClear(Dest);
  if TVarData(Source).VType in VTYPE_STATIC then
    TVarData(Dest) := TVarData(Source) else
  if true then // not SetVariantUnRefSimpleValue(Source,TVarData(Dest)) then     <<<===========
    if TVarData(Source).VType=varVariant or varByRef then
      Dest := PVariant(TVarData(Source).VPointer)^ else
      Dest := Source;
end;

Another Workaround could be - The Exception:

procedure TDocVariantData.InternalAddValue(const aName: RawUTF8; const aValue: variant);
var len: integer;
begin
  if aName<>'' then
    case Kind of // aName is set for an object
      dvUndefined:
        VKind := dvObject;
      dvArray:
        raise EDocVariant.CreateUTF8('Unexpected "%" property name in an array',[aName]);
    end else
    case Kind of // aName is not set for an array
      dvUndefined:
        VKind := dvArray;
      dvObject:
        raise EDocVariant.Create('Unexpected array item added to an object');
    end;
  if VValue=nil then
    SetLength(VValue,16) else
  if VCount>=length(VValue) then
    SetLength(VValue,VCount+VCount shr 3+32);
  if VKind=dvObject then begin
    len := length(VValue);
    if Length(VName)<>len then
      SetLength(VName,len);
    VName[VCount] := aName;
  end;
// >>>>>> ===== Old Code from 957 inserted
  if TVarData(aValue).VType=varVariant or varByRef then                 
    VValue[VCount] := PVariant(TVarData(aValue).VPointer)^ else
    VValue[VCount] := aValue;
// <<<<<< ===== Old Code from 957 inserted
  inc(VCount);
end;

The Exception raises at this point:

SynCommons.TTextWriter.AddAnyAnsiString('©xu'#2'8Ir'#2#7#0#0#0'de'#0#0#0'K║'#3'Ú²'#1#0#1#0#0... >>>> RawByteString with Length = 180088211 byte !!!
SynCommons.TTextWriter.AddVariantJSON('¸xu'#2'8Ir'#2#7,twJSONEscape)
SynCommons.TDocVariant.ToJSON($27CEAE8,???,twJSONEscape)
SynCommons.TTextWriter.AddVariantJSON(???,twJSONEscape)
SynCommons.TDocVariant.ToJSON($27CEAE8,???,twJSONEscape)
SynCommons.TTextWriter.AddVariantJSON(???,twJSONEscape)
SynCommons.TDocVariant.ToJSON($27CEAE8,???,twJSONEscape)
SynCommons.TTextWriter.AddVariantJSON(???,twJSONEscape)
SynCommons.TDocVariant.ToJSON($27CEAE8,???,twJSONEscape)
SynCommons.TTextWriter.AddVariantJSON(???,twJSONEscape)
SynCommons.TDocVariant.ToJSON($27CEAE8,???,twJSONEscape)
SynCommons.TTextWriter.AddVariantJSON(???,twJSONEscape)
mORMot.TServiceMethodArgument.AddJSON($27CEAE8,$3BA87A8)
mORMot.TServiceMethod.InternalExecute((...),'"aID',$27CEAE8,'',200,[optVariantCopiedByReference],True,nil)
mORMotMVC.TMVCRendererAbstract.ExecuteCommand(5)
...

Sry that i cannot find the exact Reason for this Problem.
But we use a lot of AddValue function Calls in the generation for one of our Pages.


Rad Studio 12.1 Santorini

Offline

#2 2015-02-26 13:50:53

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,225
Website

Re: Exception and WorkAround since 1.18.958

I do not understand well, nor was able to reproduce it with 1.18.977.
What is the TVarData(Dest).VType value in SetVariantByValue()?
For an AnsiString, the SetVariantByValue() method should return FALSE so the standard Dest := Source line should be executed in SetVariantByValue().
Is it the case on your sidE?

Online

#3 2015-02-26 16:12:24

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: Exception and WorkAround since 1.18.958

first - We use 977 for the test.
second - it workes fine with 957.
If my Patch 2 is applied it works fine with 977 again.

i have to use try and error to produce working code.
i tried a little bit found out the following:

may be it helps finding the Error.

This line of code produces the case 0/256

tdoc, temp : variant;
...
  tdoc := RestModel.RetrieveDocVariantArray(TSQLDFLRecord, '', 'AID = ? GROUP BY LGID ORDER BY CreationDate DESC', [aID], 'AID, LGID');
  if not (VarIsNull(tdoc)) then begin
    for I := 0 to DocVariantData(tdoc).Count - 1 do begin
      temp := RestModel.RetrieveDocVariantArray(TSQLDFLFRecord, '', 'ID=?', [StrToInt64(DocVariantData(tdoc).Values[i].LGID)], 'B, Beschreibung, N');
      if not VarIsNull(temp) then begin
        DocVariantData(DocVariantData(tdoc).Values[i]).AddValue('Beschreibung', DocVariantData(temp).Values[0].Beschreibung);
      end;
    end;
  end;

in case TVarData(Dest).VType = 0 and (PVarData(TVarData(Source).VPointer)^.VType = 256) i get the Exception so in that case i use the old code...

Here my actually working - Testcode...

function SetVariantUnRefSimpleValue(const Source: variant; var Dest: TVarData): boolean;
var typ: word;
begin
  if TVarData(Source).VType and varByRef<>0 then begin
    typ := TVarData(Source).VType and not varByRef;
    case typ of
    varVariant:
      //      if PVarData(TVarData(Source).VPointer)^.VType<=varNativeString  and then begin
      if (PVarData(TVarData(Source).VPointer)^.VType = 20) or
         ((PVarData(TVarData(Source).VPointer)^.VType<=varNativeString) and (TVarData(Dest).VType = 20) or
                                                                              (TVarData(Dest).VType = 59928) or
                                                                              (TVarData(Dest).VType = 59912)) then begin
        Dest := PVarData(TVarData(Source).VPointer)^;
        result := true;
      end else
        result := False;
    varNull..varDate,varBoolean,varShortInt..varWord64: begin
      Dest.VType := typ;
      Dest.VInt64 :=  PInt64(TVarData(Source).VAny)^;
      result := true;
    end;
    else
      result := false;
    end;
  end else
    result := false;
end;

Rad Studio 12.1 Santorini

Offline

#4 2015-02-26 20:00:07

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,225
Website

Re: Exception and WorkAround since 1.18.958

Could you just try

function SetVariantUnRefSimpleValue(const Source: variant; var Dest: TVarData): boolean;
var typ: word;
begin
  if TVarData(Source).VType and varByRef<>0 then begin
    typ := TVarData(Source).VType and not varByRef;
    case typ of
    varVariant: 
      if PVarData(TVarData(Source).VPointer)^.VType in VTYPE_STATIC then begin
        Dest := PVarData(TVarData(Source).VPointer)^;
        result := true;
      end else 
 ...

I suspect this is enough.

Online

#5 2015-02-26 21:25:37

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: Exception and WorkAround since 1.18.958

Hi arnaud now it works again.
tyvm


Rad Studio 12.1 Santorini

Offline

Board footer

Powered by FluxBB