Data Abstract 10 update for Delphi server app: Where's the documented changes?

There appear to be, between Data Abstract 7 up to Data Abstract 10, many breaking non backwards compatible changes.

Is there a documented list of those?

Is there still a binary DLL dependency on mozilla spidermonkey?

https://docs.dataabstract.com/BreakingChanges/

  • uDaClasses
  • TDASqlCondition defined in uDAPlainWhere
  • IDADataset.Where now called…?
  • Service Create proxy changes.

// this autogenerated service implementation creation calls a proxy which no longer contains the Create(URI) overload..
class function CoLoginService.Create(const aUri: TROUri): ILoginService;
begin
  Result := TLoginService_Proxy.Create(aUri);     // [dcc32 Error] RentalPointService_Intf.pas(88): E2250 There is no overloaded version of 'Create' that can be called with these arguments
end;

The actual proxy constructor code is now

constructor TROProxy.Create(const aRemoteService: IRORemoteService);
begin
  {$IFNDEF TROPROXY_IGNORES_REMOTESERVICE_SERVICENAME}
    Create(aRemoteService.ServiceName, aRemoteService.Message, aRemoteService.Channel);
  {$ELSE}
    Create(aRemoteService.Message, aRemoteService.Channel);
  {$ENDIF}
  CloneMessage := aRemoteService.CloneMessage;
end;


//The initialization code in the impl initialization no longer compiles...

initialization
  RegisterProxyClass(ILoginService_IID, TLoginService_Proxy);
  RegisterProxyClass(IDataService_IID, TDataService_Proxy);

I had a helper function called WhereCodes in my app that looks like this. I can not figure out how to move it forward into DA 10. It takes an IDADataset interface, and adds a where filter condition.
The IDADataset.Where is gone, there’s a DynamicWhere but there’s no similar way to add a where fieldname equal or less than some value like this helper does:


function WhereCodes(ds:IDADataset; fieldName,fieldValues:String;likeFlag:Boolean):Boolean;
var
// fieldValuesSet:String;
 s:TStringList;
 ct:Integer;
 n : Integer;
 condition:TDASqlCondition;    // TDASQLCondition enum
begin
  result := False;
  if (fieldvalues='')or(Pos('''',fieldvalues)>0)or (Pos('--',fieldValues)>0)or (Pos('/*',fieldValues)>0)  then
  begin
      exit;
  end;
  if (fieldname='')or(Pos(' ',fieldName)>0)or (Pos('''',fieldName)>0) or (Pos('--',fieldName)>0) or (Pos('/*',fieldName)>0)then
  begin
      exit;
  end;

  if likeFlag then
    condition := cLike
  else
    condition := cEqual;

  if Pos(',',fieldvalues) = 0 then
  begin
    if likeFlag then
    begin
       fieldValues := fieldValues + '%';
    end;

    ds.Where.AddCondition( fieldName, condition, fieldValues );


  end
  else
  begin

    s := TStringList.Create;
    s.Delimiter := ',';
    try
      s.DelimitedText := fieldValues;
      ct := s.Count-1;
      if s[ct]='' then
        dec(ct);
      for n := 0 to ct do
      begin
        fieldValues := s[n];
        if likeFlag then
        begin
           fieldValues := fieldValues + '%';
        end;
        ds.Where.AddCondition(fieldName,condition,fieldValues);
        if (n<ct) then
          ds.Where.AddOperator(opOR);
      end;
    finally
      s.Free;
    end;
  end;
end;

Also having problems with DA interface IMPLEMENTATIONS of a IROService service’s newly required methods… SupportInfo etc

example of an _IMPL compilation error, probably caused by uROEncoding types being new.


 { TRentalPointService }
  TRentalPointService = class(TRORemoteDataModule, IRentalPointService)
    procedure RORemoteDataModuleCreate(Sender: TObject);


[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.DoAssetOperation
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.UndoOperation
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.GetSystemInformation
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.SetRentalPointOperatorInfo
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.DoCompleteOperation
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.SupportInfo
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.UrlFor
[dcc32 Error] RentalPointService_Impl.pas(118): E2291 Missing implementation of interface method IRentalPointService.UrlForWeb
[dcc32 Fatal Error] RentalPointService_Impl.pas(1385): F2063 Could not compile used unit 'UriHelperU.pas'

Hi,

if you are using TDASpiderMonkeyScriptProvider, you need that dll

this unit was refactored and it’s content was put to other units

this is legacy feature and it’s can be considered as a security hole because allow to pass plain SQL statements from client.
We can recommend to replace it with Dynamic Where feature

you can use IDALegacyWhereSupport interface like

(ldataset as IDALegacyWhereSupport).WhereClause := ':fld = 5';

looks like you haven’t regenerated _Intf because it should be generated as

class function CoLoginService.Create(const aUri: TROUri; aDefaultNamespaces: string = ''): ILoginService;
begin
  result := TLoginService_Proxy.Create(aUri, aDefaultNamespaces);
  exit;
end;

you can use something like

//condition: TDABinaryOperator
  if likeFlag then
    condition := dboLike
  else
    condition := dboEqual;
  if Pos(',',fieldvalues) = 0 then begin
    if likeFlag then fieldValues := fieldValues + '%';

    ds.DynamicWhere.Expression := ds.DynamicWhere.NewBinaryExpression('',fieldName, condition, fieldValues);
    //AddCondition( fieldName, condition, fieldValues );
  end
  else begin
    ...
    lExpression := ds.DynamicWhere.NewBinaryExpression('',fieldName, condition, fieldValues);
	if ds.DynamicWhere.Expression = nil then 
	  ds.DynamicWhere.Expression := lExpression
	else
	  ds.DynamicWhere.Expression := ds.DynamicWhere.NewBinaryExpression(ds.DynamicWhere.Expression,lexpression, dboOR)
  end;

it does almost the same only via DynamicWhere.
another possibility to add list of “OR” expressions with ds.DynamicWhere.NewBinaryExpressionList(list, dboOR);

Nowadays we use ROAnsiString and ROUTF8String instead of AnsiString and UTF8String.
it may lead to such errors. I can recommend to copy method declarations from _Intf to _Impl

2 Likes

Here’s a sample working function. I decided to not permit the helper function to take multiple fields at once.

Instead it will simply add one condition to something that has none, or keep adding ors, and you call this function one time per filter criteria you want applied to the results.

I hope this function might be helpful to someone.


// In Data Abstract 7 there was a different set of where functions.
// Those were retired in Data Abstract 8, we are now on Data Abstract 10
// as of 2022
//
// This helper function makes it easier to filter datasets.
//
// If you call it twice, it should keep both conditions with an OR or AND
//    WhereCode(ds, 'FIELDA', 'ABC', false); // filter where FIELD='ABC'
//    WhereCode(ds, 'FIELDB', 'DEF', false); // filter where FIELD='ABC'
//  Above should return either FIELDA=ABC OR FIELDB=DEF.
//
//  Parameter 5 is an and-flag (replaces default or).
//    WhereCode(ds, 'FIELDA', 'ABC', false, true); // filter where FIELD='ABC'
//    WhereCode(ds, 'FIELDB', 'DEF', false, true); // filter where FIELD='ABC'
//  Above should return either FIELDA=ABC AND FIELDB=DEF.

//
function WhereCode(ds:IDADataset; fieldName,fieldValue:String;likeFlag:Boolean=false;andFlag:Boolean=false):Boolean;
var
 s:TStringList;
 ct:Integer;
 n : Integer;
 condition:TDABinaryOperator; //TDASqlCondition;    // TDASQLCondition enum
 lExpression: TDAWhereExpression;
begin
  result := False;
  if  (fieldvalue='') or
      (Pos('--',fieldValue)>0)  or
      ( Pos('/*',fieldValue) > 0 )  or
      (Pos(',',fieldValue)>0)or
      (Pos('"',fieldValue)>0)
      then
  begin
      raise Exception.Create('Invalid field value. Special character not allowed.');
      exit;
  end;
  if (fieldname='')or(Pos(' ',fieldName)>0)or (Pos('''',fieldName)>0) or (Pos('--',fieldName)>0) or (Pos('/*',fieldName)>0)then
  begin
      raise Exception.Create('Invalid field name. Special character not allowed.');
      exit;
  end;

  if likeFlag then
    condition := dboLike
  else
    condition := dboEqual;



  if likeFlag then
  begin
     fieldValue := fieldValue + '%';
  end;

  (*
      class function TDAWhereBuilder.NewBinaryExpression(
              const aTableName,
              aFieldName: string;
              anOp: TDABinaryOperator;
              const aValue: variant): TDAWhereExpression;

  *)
  lExpression := ds.DynamicWhere.NewBinaryExpression('',fieldName, condition, fieldValue );
	if ds.DynamicWhere.Expression = nil then
	  ds.DynamicWhere.Expression := lExpression
	else
  begin
    if andFlag then
    	  ds.DynamicWhere.Expression := ds.DynamicWhere.NewBinaryExpression(ds.DynamicWhere.Expression,lexpression, dboAND)
    else
    	  ds.DynamicWhere.Expression := ds.DynamicWhere.NewBinaryExpression(ds.DynamicWhere.Expression,lexpression, dboOR)
  end;
end;