From 41b832ceb61dc9148a23a2dddebaef904c83c53c Mon Sep 17 00:00:00 2001 From: Roniery Santos Cardoso Date: Tue, 2 Sep 2025 18:36:55 -0300 Subject: [PATCH] Ajustes em ftArray, JsonInterface e ClientSQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Suporte a campos ftArray como String (limite inicial 255). - Correções de Null/NullClass na JsonInterface (inclui Lazarus). - Remoção de memory leaks em Lazarus/FPC. - Propriedade BinaryRequest removida do ClientSQL (padrão binário será no ClientPooler). - Ajuste da numeração de versão. --- CORE/Source/Basic/uRESTDWBasicDB.pas | 2 +- CORE/Source/Basic/uRESTDWStorageBin.pas | 36 ++++- CORE/Source/Consts/uRESTDWConsts.pas | 6 +- CORE/Source/Sockets/Indy/uRESTDWIdBase.pas | 3 - CORE/Source/utils/JSON/uRESTDWJSON.pas | 127 +++++++++++------- .../utils/JSON/uRESTDWJSONInterface.pas | 9 +- CORE/Source/utils/uRESTDWTools.pas | 4 +- 7 files changed, 118 insertions(+), 69 deletions(-) diff --git a/CORE/Source/Basic/uRESTDWBasicDB.pas b/CORE/Source/Basic/uRESTDWBasicDB.pas index 09687746..3a63a5e0 100644 --- a/CORE/Source/Basic/uRESTDWBasicDB.pas +++ b/CORE/Source/Basic/uRESTDWBasicDB.pas @@ -817,13 +817,13 @@ interface Property FieldDefs; Property ReadData : Boolean Read GetReadData; Property MasterDetailList : TMasterDetailList Read vMasterDetailList Write vMasterDetailList; + Property BinaryRequest : Boolean Read vBinaryRequest; // Write vBinaryRequest; Published Property MasterDataSet : TRESTDWClientSQL Read vMasterDataSet Write SetMasterDataSet; {$IFDEF FPC} Property DatabaseCharSet; {$ENDIF} Property MasterCascadeDelete : Boolean Read vCascadeDelete Write vCascadeDelete; - Property BinaryRequest : Boolean Read vBinaryRequest Write vBinaryRequest; Property Datapacks : Integer Read vDatapacks Write SetDatapacks; Property OnGetDataError : TOnEventConnection Read vOnGetDataError Write vOnGetDataError; //Recebe os Erros de ExecSQL ou de GetData Property AfterScroll : TOnAfterScroll Read vOnAfterScroll Write vOnAfterScroll; diff --git a/CORE/Source/Basic/uRESTDWStorageBin.pas b/CORE/Source/Basic/uRESTDWStorageBin.pas index f903afbd..8284ba44 100644 --- a/CORE/Source/Basic/uRESTDWStorageBin.pas +++ b/CORE/Source/Basic/uRESTDWStorageBin.pas @@ -160,10 +160,22 @@ interface AStream.Read(vFieldType, SizeOf(vFieldType)); vFieldDef.DataType := DWFieldTypeToFieldType(vFieldType); FFieldTypes[I] := vFieldType; + + If vFieldType in [{$IFDEF FPC}45, {$ENDIF}dwftExtended] Then + FFieldTypes[I] := {$IFDEF FPC}Integer(ftFMTBcd){$ELSE}Integer(ftExtended){$ENDIF} + Else + FFieldTypes[I] := vFieldType; // field size AStream.Read(vInt, SizeOf(vInt)); + If vFieldType = dwftVarBytes Then //Max Array Size + Begin + FFieldTypes[I] := Integer(ftString); + FFieldSize[I] := 255; + vInt := FFieldSize[I]; + End + Else + FFieldSize[I] := vInt; vFieldDef.Size := vInt; - FFieldSize[I] := vInt; // field precision AStream.Read(vInt, SizeOf(vInt)); FFieldPrecision[I] := vInt; @@ -341,7 +353,13 @@ interface FFieldTypes[I] := vFieldType; // field size AStream.Read(vFieldSize, SizeOf(vFieldSize)); - FFieldSize[I] := vFieldSize; + If vFieldType = dwftVarBytes Then //Max Array Size + Begin + FFieldTypes[I] := Integer(ftString); + FFieldSize[I] := 255; + End + Else + FFieldSize[I] := vFieldSize; // field precision AStream.Read(vFieldPrecision, SizeOf(vFieldPrecision)); {$IFDEF FPC} @@ -589,8 +607,9 @@ interface End; End; // N Bytes - Strings + dwftVarBytes, dwftFixedChar, - dwftString :Begin + dwftString : Begin stream.Read(vInt64, SizeOf(vInt64)); vString := ''; If vInt64 > 0 Then @@ -611,7 +630,7 @@ interface Move(vString[InitStrPos], pData^, Length(vString)); {$ENDIF} End; - End; + End; // 1 - Byte - Inteiro dwftByte, dwftShortint :Begin @@ -888,7 +907,7 @@ interface dwftStream, dwftOraBlob, dwftBlob, - dwftBytes :Begin + dwftBytes : Begin SetLength(vBytes, 0); stream.Read(vInt64, SizeOf(DWInt64)); If vInt64 > 0 Then @@ -906,7 +925,7 @@ interface Finally SetLength(vBytes, 0); End; - End; + End; // N Bytes - Others Else Begin @@ -975,6 +994,7 @@ interface If (FFieldTypes[i] In [dwftFixedChar, dwftWideString, dwftString, + dwftVarBytes, dwftFixedWideChar]) Then Begin AStream.Read(vInt64, Sizeof(vInt64)); @@ -1291,7 +1311,7 @@ interface dwftWideString : vByte := FieldTypeToDWFieldType(ftString); dwftSingle : vByte := FieldTypeToDWFieldType(ftFloat); End; - AStream.Write(vByte, SizeOf(vByte)); + AStream.Write(vByte, SizeOf(vByte)); // fieldsize vInt := ADataset.Fields[i].Size; AStream.Write(vInt, SizeOf(vInt)); @@ -1427,6 +1447,7 @@ interface Stream.Write(vString[1], vInt64); {$ENDIF} End; + dwftVarBytes, dwftString : Begin {$IFDEF RESTDWANDROID} vString := MarshaledAString(PData); @@ -1658,6 +1679,7 @@ interface AStream.Write(vString[InitStrPos], vInt64); End; // N - Bytes + dwftVarBytes, dwftString : Begin vString := ADataset.Fields[i].AsString; If EncodeStrs Then diff --git a/CORE/Source/Consts/uRESTDWConsts.pas b/CORE/Source/Consts/uRESTDWConsts.pas index 6f94dd30..6d9ac880 100644 --- a/CORE/Source/Consts/uRESTDWConsts.pas +++ b/CORE/Source/Consts/uRESTDWConsts.pas @@ -1,4 +1,4 @@ -Unit uRESTDWConsts; +Unit uRESTDWConsts; {$I ..\..\Source\Includes\uRESTDW.inc} @@ -60,8 +60,8 @@ // controle de versão RESTDWVersionINFO = 'v2.1.0-'; - RESTDWRelease = '3857'; - RESTDWCodeProject = 'Galaga - SourceForge'; + RESTDWRelease = '3974'; + RESTDWCodeProject = 'Final Fantasy X - GitHub'; RESTDWVersao = RESTDWVersionINFO + RESTDWRelease + '(' + RESTDWCodeProject + ')'; RESTDWDialogoTitulo = 'REST DataWare Components ' + RESTDWVersao; RESTDWSobreTitulo = 'REST DataWare '+ RESTDWVersao; diff --git a/CORE/Source/Sockets/Indy/uRESTDWIdBase.pas b/CORE/Source/Sockets/Indy/uRESTDWIdBase.pas index df64f993..00f47397 100644 --- a/CORE/Source/Sockets/Indy/uRESTDWIdBase.pas +++ b/CORE/Source/Sockets/Indy/uRESTDWIdBase.pas @@ -3281,7 +3281,6 @@ TIdHTTPAccess = class(TIdHTTP) {$IFEND} vAuthRealm := AResponseInfo.AuthRealm; vContentType := ARequestInfo.ContentType; - If CommandExec (TComponent(AContext), RemoveBackslashCommands(ARequestInfo.URI), ARequestInfo.RawHTTPCommand, @@ -3898,10 +3897,8 @@ function TRESTDWIdClientPooler.IsServerLive(Aip: String; Aport: Integer; If Assigned(bJsonOBJ) Then FreeAndNil(bJsonOBJ); End; - {$IFNDEF FPC} //TODO XyberX If Assigned(bJsonValue) Then FreeAndNil(bJsonValue); - {$ENDIF} End; Finally If vTempValue <> '' Then diff --git a/CORE/Source/utils/JSON/uRESTDWJSON.pas b/CORE/Source/utils/JSON/uRESTDWJSON.pas index 959d8d3c..aa613bcb 100644 --- a/CORE/Source/utils/JSON/uRESTDWJSON.pas +++ b/CORE/Source/utils/JSON/uRESTDWJSON.pas @@ -358,7 +358,7 @@ TJSONArray = class (TZAbstractObject) function toString (indentFactor, indent : integer) : string; overload; function toList () : TList; private - myArrayList : TList; + myArrayList : TList; aJSONTokener : JSONTokener; end; @@ -765,11 +765,14 @@ function JSONTokener.nextValue: TZAbstractObject; c, b : char; s , sb: string; begin - c := nextClean(); + Result := Nil; + c := nextClean(); case (c) of '"', #39: begin - result := _String.create (nextString(c)); + s := nextString(c); + If s <> '' Then + result := _String.create(s); exit; end; '{': begin @@ -1055,7 +1058,8 @@ constructor TJSONObject.create(x: JSONTokener); end else if (c <> ':') then begin raise x.syntaxError('Expected a ":" after a key'); end; - self.myHashMap.AddObject(key, x.nextValue()); + If key <> '' Then + self.myHashMap.AddObject(key, x.nextValue()); (* * Pairs are separated by ','. We will also tolerate ';'. @@ -1063,14 +1067,13 @@ constructor TJSONObject.create(x: JSONTokener); case (x.nextClean()) of ';', ',': begin - if (x.nextClean() = '}') then begin - exit; - end; - x.back(); - end; + if (x.nextClean() = '}') then + exit; + x.back(); + end; '}': begin - exit; - end + exit; + end else begin raise x.syntaxError('Expected a "," or "}"'); end @@ -1085,19 +1088,18 @@ constructor TJSONObject.create(map: TStringList); i : integer; begin self.myHashMap := TStringlist.create; - for i := 0 to map.Count -1 do begin - self.myHashMap.AddObject(map[i],map.Objects[i]); - end; + for i := 0 to map.Count -1 do + self.myHashMap.AddObject(map[i], map.Objects[i]); end; constructor TJSONObject.create(s: string); var - token : JSOnTokener; + token : JSOnTokener; begin token := JSONTokener.create(s); create (token); - token.free; + FreeAndNil(token); end; @@ -1142,15 +1144,17 @@ function TJSONObject.accumulate(key: string; value: TZAbstractObject): TJSONObje * @raises (NoSuchElementException if the key is not found.) *) function TJSONObject.get(key: string): TZAbstractObject; -var +Var o : TZAbstractObject; begin - o := opt(key); - if (o = nil) then begin - raise NoSuchElementException.create('TJSONObject[' + - quote(key) + '] not found.'); - end; - result := o; + o := opt(key); + If (o = nil) Then + Begin + Raise NoSuchElementException.create('TJSONObject[' + + quote(key) + '] not found.'); + Exit; + End; + Result := o; end; @@ -1309,9 +1313,8 @@ function TJSONObject.keys: TStringList; i : integer; begin result := TStringList.Create; - for i := 0 to myHashMap.Count -1 do begin - result.add (myHashMap[i]); - end; + for i := 0 to myHashMap.Count -1 do + result.add (myHashMap[i]); end; function TJSONObject.length: integer; @@ -1824,7 +1827,15 @@ function TJSONObject.toString: string; o := _keys[i]; sb := sb + quote(o); sb := sb + ':'; - sb:= sb + valueToString(TZAbstractObject(myHashMap.Objects[myHashMap.IndexOf(o)])); + If myHashMap.IndexOf(o) > -1 Then + Begin + If Assigned(myHashMap.Objects[myHashMap.IndexOf(o)]) Then + sb:= sb + valueToString(TZAbstractObject(myHashMap.Objects[myHashMap.IndexOf(o)])) + Else + sb:= sb + 'null'; + End + Else + sb:= sb + 'null'; end; sb := sb + '}'; result := sb; @@ -1924,20 +1935,25 @@ class function TJSONObject.NULL: NULL; class function TJSONObject.valueToString(value: TZAbstractObject): string; begin - if ((value = nil) or (value.equals(null))) then begin + Try + if ((value = nil) or (TZAbstractObject(Pointer(@value)^) = cNull)) then begin result := 'null'; exit; end; - if (value is _Number) then begin - result := numberToString(_Number(value)); + if ((TZAbstractObject(Pointer(@value)^) is _Number) Or + (TZAbstractObject(Pointer(@value)^).ClassParent = _Number)) then begin + result := numberToString(_Number(TZAbstractObject(Pointer(@value)^))); exit; end; - if ((value is _Boolean) or (value is TJSONObject) or - (value is TJSONArray)) then begin - result := value.toString(); + if ((TZAbstractObject(Pointer(@value)^) is _Boolean) or (value is TJSONObject) or + (TZAbstractObject(Pointer(@value)^) is TJSONArray)) then begin + result := TZAbstractObject(Pointer(@value)^).toString(); exit; end; - result := quote(value.toString()); + result := quote(TZAbstractObject(Pointer(@value)^).toString()); + Except + Result := 'null'; + End; end; @@ -2179,6 +2195,8 @@ function _Double.toString: string; * @raises (ParseException Expected a ',' or ']') *) constructor TJSONArray.create(x: JSONTokener); +Var + vAbstractObject : TZAbstractObject; begin create; if (x.nextClean() <> '[') then begin @@ -2194,7 +2212,9 @@ constructor TJSONArray.create(x: JSONTokener); myArrayList.add(nil); end else begin x.back(); - myArrayList.add(x.nextValue()); + vAbstractObject := x.nextValue(); + If Assigned(vAbstractObject) Then + myArrayList.add(vAbstractObject); end; case (x.nextClean()) of ';',',': begin @@ -2263,11 +2283,9 @@ destructor TJSONArray.destroy; while myArrayList.Count > 0 do begin obj := TObject(myArrayList[0]); myArrayList [0] := nil; - if (obj <> CONST_FALSE) - and (obj <> CONST_TRUE) - and (obj <> CNULL) then begin - obj.Free; - end; + If (obj <> CONST_FALSE) And + (obj <> CONST_TRUE) Then + FreeAndNil(obj); myArrayList.Delete(0); end; FreeAndNil(myArrayList); @@ -2470,7 +2488,10 @@ function TJSONArray.join(separator: string): string; if (i > 0) then begin sb := sb + separator; end; - s := TJSONObject.valueToString(TZAbstractObject( myArrayList[i])); + If Assigned(myArrayList[i]) Then + s := TJSONObject.valueToString(TZAbstractObject( myArrayList[i])) + Else + s := 'null'; sb:= sb + s; end; result := sb; @@ -2990,10 +3011,16 @@ procedure TJSONObject.clean; begin while myHashMap.Count > 0 do begin if (myHashMap.Objects [0] <> CONST_FALSE) + and (myHashMap.Objects [0] <> Nil) and (myHashMap.Objects [0] <> CONST_TRUE) - and (myHashMap.Objects [0] <> CNULL) then begin - myHashMap.Objects [0].Free; - end; + and (myHashMap.Objects [0] <> CNULL) then + begin + If Assigned(myHashMap.Objects[0]) Then + Begin + myHashMap.Objects[0].Free; + myHashMap.Objects[0] := Nil; + End; + end; myHashMap.Objects [0] := nil; myHashMap.Delete(0); end; @@ -3032,12 +3059,12 @@ function TJSONObject.clone: TZAbstractObject; initialization - CONST_FALSE := _Boolean.create (false); - CONST_TRUE := _Boolean.create (true); - CNULL := NULL.create; + CONST_FALSE := _Boolean.create (false); + CONST_TRUE := _Boolean.create (true); + CNULL := NULL.create; finalization - CONST_FALSE.free; - CONST_TRUE.Free; - CNULL.free; + FreeAndNil(CONST_FALSE); + FreeAndNil(CONST_TRUE); + FreeAndNil(CNULL); end. diff --git a/CORE/Source/utils/JSON/uRESTDWJSONInterface.pas b/CORE/Source/utils/JSON/uRESTDWJSONInterface.pas index 59b8d067..a74f6130 100644 --- a/CORE/Source/utils/JSON/uRESTDWJSONInterface.pas +++ b/CORE/Source/utils/JSON/uRESTDWJSONInterface.pas @@ -602,10 +602,13 @@ implementation Begin result.Name := cNames.Get(index).toString; Try - result.Value := TJSONObject(vJSONObject).Get(result.Name).toString; + IF (TJSONObject(vJSONObject).Get(result.Name) <> Nil) And + (TJSONObject(vJSONObject).Get(result.Name) <> CNULL) Then + result.Value := TJSONObject(vJSONObject).Get(result.Name).toString; Except + result.Value := ''; End; - result.ClassName := TJSONObject(vJSONObject).Get(result.Name).ClassName; + result.ClassName := cNames.Get(index).ClassName; End; End Else @@ -676,7 +679,7 @@ implementation If Trim(result.ClassName) = '' Then result.ClassName := vClassName; // Correção para null value - result.isnull := (result.Value = 'null'); // or (Result.Value = ''); + result.isnull := (result.Value = 'null') or (Result.Value = ''); If result.isnull Then result.Value := ''; End; diff --git a/CORE/Source/utils/uRESTDWTools.pas b/CORE/Source/utils/uRESTDWTools.pas index ef763554..1674012f 100644 --- a/CORE/Source/utils/uRESTDWTools.pas +++ b/CORE/Source/utils/uRESTDWTools.pas @@ -569,7 +569,7 @@ interface dwftTime : Result := ftTime; dwftDateTime : Result := ftDateTime; dwftBytes : Result := ftBytes; - dwftVarBytes : Result := ftVarBytes; + dwftVarBytes : Result := ftString; dwftAutoInc : Result := ftAutoInc; dwftBlob : Result := ftBlob; dwftMemo : Result := ftMemo; @@ -668,7 +668,7 @@ interface ftWideString : Result := dwftWideString; ftLargeint : Result := dwftLargeint; ftADT : Result := dwftADT; - ftArray : Result := dwftArray; + ftArray : Result := dwftVarBytes; ftReference : Result := dwftReference; ftDataSet : Result := dwftDataSet; ftOraBlob : Result := dwftOraBlob;