unit uSchemaUtilsServer; interface uses Classes, SysUtils, uROClientIntf, uROTypes, uROServer, uROServerIntf, uROSessions, DataAbstract4_Intf, DataAbstractService_Impl, uDAClasses, uDAInterfaces, uDADataTable; type TReplicarDataSet = class protected function GenerateNewSQL : String; public Service : TDataAbstractService; Columnas : String; ColumnasQueSuman : String; ColumnasQueAVG : String; SourceDataSetName : String; function GetNewDataSet : IDADataset; end; implementation { TReplicaDataSet } uses RegExpr, Dialogs, JclStrings; function TReplicarDataSet.GenerateNewSQL: String; var AColumnList : TStringList; ASQL: TStringList; ds : IDADataset; i : integer; Separador : String; bHayAgrupacion : Boolean; function GetTrueFieldName(AField : string; ConAlias : Boolean = True) : String; var ARegExpr : TRegExpr; begin Result := AField; // Por si el campo no tuviera alias ARegExpr := TRegExpr.Create; try ARegExpr.ModifierI := True; // case insensitive ARegExpr.InputString := ds.SQL; ARegExpr.Expression := '[^ ,]+[ ]+AS[ ]+' + AField; // buscar (xxxx.xxxx AS AField) o (xxxx AS AField) ARegExpr.Expression := ARegExpr.Expression + '|'; // o ARegExpr.Expression := ARegExpr.Expression + '[^ ,]+\.' + AField; // buscar xxxx.AField if ARegExpr.Exec then Result := ARegExpr.Match[0]; if not ConAlias then begin ARegExpr.InputString := Result; ARegExpr.Expression := '^[^ ,]+'; // Para quedarme con el campo sin alias if ARegExpr.Exec then Result := ARegExpr.Match[0] end; finally FreeAndNil(ARegExpr); end; end; begin AColumnList := TStringList.Create; ASQL := TStringList.Create; ds := Service.ServiceSchema.NewDataset(Service.Connection, SourceDataSetName); bHayAgrupacion := False; try AColumnList.CommaText := Columnas; with ASQL do begin Insert(0, 'SELECT DISTINCT'); Insert(1, ''); // Lista de campos Insert(2, Copy(ds.SQL, Pos('FROM', ds.SQL), Length(ds.SQL))); Insert(3, ''); // Group by Separador := ''; for i := 0 to AColumnList.Count - 1 do begin if Assigned(ds.FindField(AColumnList[i])) then begin if i > 0 then Separador := ','; if Pos('#'+AColumnList[i]+'#', ColumnasQueSuman) > 0 then begin Strings[1] := Strings[1] + Separador + 'SUM(' + GetTrueFieldName(AColumnList[i], False) + ') AS ' + AColumnList[i]; bHayAgrupacion := True; end else if Pos('#'+AColumnList[i]+'#', ColumnasQueAVG) > 0 then begin Strings[1] := Strings[1] + Separador + 'AVG(' + GetTrueFieldName(AColumnList[i], False) + ') AS ' + AColumnList[i]; bHayAgrupacion := True; end else begin Strings[1] := Strings[1] + Separador + GetTrueFieldName(AColumnList[i]); if Length(Strings[3]) = 0 then Strings[3] := 'GROUP BY ' else begin if (Strings[3] <> 'GROUP BY ') then Strings[3] := Strings[3] + Separador; end; Strings[3] := Strings[3] + GetTrueFieldName(AColumnList[i], False); end; end; end; // for if not bHayAgrupacion then Delete(3); end; Result := ASQL.Text; finally AColumnList.Free; ASQL.Free; end; end; function TReplicarDataSet.GetNewDataSet: IDADataset; var SQL: String; ASchemaDataSet: TDADataSet; AColumnList : TStringList; i, j : Integer; begin SQL := GenerateNewSQL; Result := Service.Connection.NewDataset(SQL, SourceDataSetName); ASchemaDataSet := Service.ServiceSchema.Datasets.DatasetByName(SourceDataSetName); if Assigned(ASchemaDataSet) then begin Result.Params.AssignParamCollection(ASchemaDataSet.Params); Result.Fields.AssignFieldCollection(ASchemaDataSet.Fields); AColumnList := TStringList.Create; try AColumnList.CommaText := Columnas; j := 0; i := Result.Fields.Count; while i > 0 do begin if AColumnList.IndexOf(Result.Fields[j].Name) = -1 then Result.Fields.Delete(j) else j := j + 1; // Un campo que dejo i := i - 1; // Un campo menos por revisar end; finally AColumnList.Free; end; end; Result.Close; Result.Where.Clear; end; end.