unit uDAHelpers; {----------------------------------------------------------------------------} { Data Abstract Library - Core Library } { } { compiler: Delphi 6 and up, Kylix 3 and up } { platform: Win32, Linux } { } { (c)opyright RemObjects Software. all rights reserved. } { } { Using this code requires a valid license of the Data Abstract } { which can be obtained at http://www.remobjects.com. } {----------------------------------------------------------------------------} {$I DataAbstract.inc} interface uses {$IFDEF MSWINDOWS}Windows,{$ENDIF} uDAInterfaces, uDAInterfacesEx, uDAClasses, Classes, uDASupportClasses; function BuildSelectStatementForTable(iTableName: string; iConnection: IDAConnection): string; function BuildJoinedSelectStatementForTables(iTableNames: array of string; iConnection: IDAConnection): string; function BuildCreateStatementForTable(aDataSet:TDADataSet; const aTableName:string; iConnection: IDAConnectionModelling): string; function BuildExecStatementForProcedure(const iProcedureName: string; iConnection: IDAConnection): string; function QuoteIfNeeded(iTableName: string; iConnection: IDAConnection = nil): string; function QuoteFieldNameIfNeeded(iTableName, iFieldName: string; iConnection: IDAConnection): string; function FindUniqueName(const iBaseName:string; iCollection: TSearcheableCollection):string; procedure CreateNewDatasets(aSchema: TDASchema; aConnection: IDAConnection; aTables: TStrings; aCreateComandsToo: boolean=false; aCreateRelationships: boolean=false; aListCreatedDatasets:TList=nil; aShowDataset:boolean=true); function LoadHtmlFromResource(aInstance: THandle; const aName: string): string; implementation uses SysUtils, uROClasses, Contnrs; function LoadHtmlFromResource(aInstance: THandle; const aName: string): string; {$IFDEF MSWINDOWS} var lResource,lData: THandle; p:pChar; {$ENDIF} begin result := ''; {$IFDEF MSWINDOWS} lResource := FindResource(aInstance, pChar(aName), pChar(2110)); if (lResource > 0) then begin lData := LoadResource(aInstance, lResource); p := LockResource(lData); try if Assigned(p) then begin result := p; UniqueString(result); end; finally UnlockResource(lData) end; end; {$ENDIF} end; function BuildCreateStatementForTable(aDataSet:TDADataSet; const aTableName:string; iConnection: IDAConnectionModelling): string; var i: integer; lCurrentLine, lPrimary: string; begin result := 'CREATE TABLE '+QuoteIfNeeded(aTableName, iConnection)+ #13#10'('; for i := 0 to (aDataSet.Fields.Count - 1) do begin lCurrentLine := ' '+ QuoteIfNeeded(aDataSet.Fields[i].Name, iConnection)+ ' '+ iConnection.FieldToDeclaration(aDataSet.Fields[i]); if (i < aDataSet.Fields.Count - 1) then lCurrentLine := lCurrentLine + ', '; result := result+#13#10+lCurrentLine; end; lPrimary := ''; for i := 0 to (aDataSet.Fields.Count - 1) do if aDataSet.Fields[i].InPrimaryKey then begin if lPrimary <> '' then lPrimary := lPrimary+','#13#10; lPrimary := lPrimary+ ' '+ QuoteIfNeeded(aDataSet.Fields.Fields[i].Name, iConnection); end; if lPrimary <> '' then begin result := result+','#13#10+ 'CONSTRAINT '+QuoteIfNeeded('PK_'+aTableName)+' PRIMARY KEY'#13#10+ ' ('#13#10+ lPrimary+#13#10+ ' )' end; result := result+#13#10')'; end; function BuildSelectStatementForTable(iTableName: string; iConnection: IDAConnection): string; var lFields: TDAFieldCollection; i: integer; lCurrentLine, lQuery: string; begin iConnection.GetTableFields(iTableName, lFields); if Assigned(lFields) then try lCurrentLine := ''; lQuery := ''; for i := 0 to (lFields.Count - 1) do begin lCurrentLine := lCurrentLine + QuoteFieldNameIfNeeded(iTableName,lFields.Fields[i].Name, iConnection); if (i < lFields.Count - 1) then begin lCurrentLine := lCurrentLine + ', '; if Length(lCurrentLine) > 50 then begin lQuery := lQuery + lCurrentLine + #13#10' '; lCurrentLine := ''; end; end; end; result := 'SELECT ' + #13#10' ' + lQuery + lCurrentLine + #13#10' FROM'#13#10' ' + QuoteIfNeeded(iTableName, iConnection)+ #13#10' WHERE {Where}'; finally FreeAndNil(lFields); end else begin result := 'SELECT * FROM ' + QuoteIfNeeded(iTableName, iConnection)+ #13#10' WHERE {Where}'; end; end; function BuildJoinedSelectStatementForTables(iTableNames: array of string; iConnection: IDAConnection): string; var lTableName: string; lFields: TDAFieldCollection; i,j: integer; lCurrentLine, lQuery: string; begin Result:=''; for i := Low(iTableNames) to High(iTableNames) do begin lTableName := QuoteIfNeeded(iTableNames[i], iConnection); if result = '' then result := 'SELECT '#13#10 else result := result+', '#13#10; iConnection.GetTableFields(iTableNames[i], lFields); if Assigned(lFields) then try lCurrentLine := ' '; lQuery := ''; for j := 0 to (lFields.Count - 1) do begin lCurrentLine := lCurrentLine + lTableName+'.'+QuoteIfNeeded(lFields.Fields[j].Name, iConnection); if (j < lFields.Count - 1) then begin lCurrentLine := lCurrentLine + ', '; if Length(lCurrentLine) > 50 then begin lQuery := lQuery + lCurrentLine + #13#10' '; lCurrentLine := ''; end; end; end; result := result + lQuery + lCurrentLine; finally FreeAndNil(lFields); end else begin result := result + QuoteIfNeeded(iTableNames[i], iConnection)+'*'; end; end; for i := Low(iTableNames) to High(iTableNames) do begin if i = 0 then begin result := result+#13#10' FROM '+QuoteIfNeeded(iTableNames[i], iConnection) end else begin result := result+#13#10' LEFT OUTER JOIN '+QuoteIfNeeded(iTableNames[i], iConnection)+' ON ' end; end; result := Result + #13#10' WHERE {Where}'; end; function BuildExecStatementForProcedure(const iProcedureName: string; iConnection: IDAConnection): string; var lParams: TDAParamCollection; lName: string; i: integer; lQuery: string; begin iConnection.GetStoredProcedureParams(iProcedureName, lParams); try lQuery := ''; if lParams <> nil then begin for i := 0 to (lParams.Count - 1) do begin lName := ':' + QuoteIfNeeded(lParams.Params[i].Name, iConnection); if not (lParams.Params[i].ParamType in [daptInput, daptInputOutput]) then continue; if lQuery <> '' then lQuery := lQuery + ', '; lQuery := lQuery + lName; end; end; Result := iConnection.GetSPSelectSyntax(lQuery <> ''); if Result = '' then Result := 'EXEC {0} {1}'; Result := StringReplace(Result, '{0}', QuoteIfNeeded(iProcedureName, iConnection), []); Result := StringReplace(Result, '{1}', lQuery, [rfReplaceAll]); Result := StringReplace(Result, '{{', '{', [rfReplaceAll]); finally FreeAndNil(lParams); end end; function QuoteFieldNameIfNeeded(iTableName, iFieldName: string; iConnection: IDAConnection): string; begin if Assigned(iConnection) then begin result := iConnection.QuoteFieldNameIfNeeded(iTableName,iFieldName); end else if Pos(' ', iFieldName) > 0 then begin result := '"' + iFieldName + '"'; if Pos(' ', iTableName) > 0 then Result:= '"' + iTableName + '".'+ result; end else begin result := iFieldName; end; end; function QuoteIfNeeded(iTableName: string; iConnection: IDAConnection): string; begin if Assigned(iConnection) then begin result := iConnection.QuoteIdentifierIfNeeded(iTableName); end else if Pos(' ', iTableName) > 0 then begin result := '"' + iTableName + '"'; end else begin result := iTableName; end; end; function FindUniqueName(const iBaseName:string; iCollection: TSearcheableCollection):string; var lIndex:integer; begin result := iBaseName; lIndex := 0; while Assigned(iCollection.FindItem(result)) do begin inc(lIndex); result := iBaseName+IntToStr(lIndex); end; end; procedure CreateNewDatasets(aSchema: TDASchema; aConnection: IDAConnection; aTables: TStrings; aCreateComandsToo: boolean=false; aCreateRelationships: boolean=false; aListCreatedDatasets:TList=nil; aShowDataset:boolean=true); var i,j: Integer; lKeys: TDADriverForeignKeyCollection; lSourceTableName, lDataTableName : string; lFields: TDAFieldCollection; k, z : integer; lNewDataset, lFKDataset, lPKDataset : TDADataset; lNewDatasets: TObjectList; begin // keep a listof the new datasets, so we can access them by the k index when // looking for FK matches lNewDatasets := TObjectList.Create(false); try for k := 0 to aTables.Count-1 do begin lSourceTableName := aTables[k]; lDataTableName := FindUniqueName(TrimAndClean(lSourceTableName), aSchema.Datasets); // Creates the Dataset and the fields aConnection.GetTableFields(lSourceTableName, lFields); lNewDataset := aSchema.Datasets.Add; with lNewDataset do begin Name := lDataTableName; Fields.AssignFieldCollection(lFields); end; lNewDatasets.Add(lNewDataSet); // Adds the SQL statement with lNewDataset.Statements.Add do begin if aConnection.ConnectionType <> '' then begin Connection := ''; ConnectionType := aConnection.ConnectionType; end else Connection := aConnection.Name; //Default := true; TargetTable := lSourceTableName; //SQL := 'SELECT '#13#10' '; for z := 0 to (lNewDataset.Fields.Count-1) do begin //SQL := SQL+newDataset.Fields[z].Name; if (z < lNewDataset.Fields.Count-1) then SQL := SQL+', '; // Creates the default mappings with ColumnMappings.Add do begin DatasetField := lNewDataset.Fields[z].Name; TableField := lNewDataset.Fields[z].Name; end; end; //SQL := SQL+#13#10' FROM '+QuoteIfNeeded(tblname); //SQL := BuildSelectStatementForTable(lSourceTableName, aConnection); StatementType := stAutoSQL; end; // activate the LAST one {if aShowDataset and (k = aTables.Count-1) then begin pc_MainPages.ActivePage := ts_DatasetAndCommand; pc_DatasetAndCommandTop.ActivePage := ts_Dataset2; pc_DatasetAndCommandBottom.ActivePage := ts_Dataset3; pc_DatasetPages.ActivePage := ts_DatasetStatements; ActiveControl := insp_Dataset; insp_Dataset.FocusedField := SchemaModelerData.DatasetsName; end;} // Refreshes the listview //SchemaModelerData.Datasets.Refresh; //SchemaModelerData.Datasets.Index := lNewDataset.Index; //if aCreateComandsToo then //DropCommandNewCommandsForDataset(); end; if aCreateRelationships then begin aConnection.GetForeignKeys(lKeys); if assigned(lKeys) then try for i := 0 to lKeys.Count - 1 do begin for j := 0 to lNewDatasets.Count-1 do begin lFKDataset := (lNewDatasets[j] as TDADataSet); if lKeys[i].FKTable = lFKDataset.Name then begin for k := 0 to lNewDatasets.Count-1 do begin lPKDataset := (lNewDatasets[k] as TDADataSet); if lKeys[i].PKTable = lPKDataset.Name then begin with aSchema.RelationShips.Add() do begin Name := Format('FK_%s_%s',[lFKDataset.Name, lPKDataset.Name]); MasterDatasetName := lPKDataset.Name; DetailDatasetName := lFKDataset.Name; MasterFields := lKeys[i].PKField; DetailFields := lKeys[i].FKField; end; break; { break for k } end; end; { for k (PKDataset)} break; { break for j } end; { if FK matches } end; { for j (FKDaatSet) } end; { for i (key) } finally lKeys.Free(); end; end; if Assigned(aListCreatedDatasets) then begin for i := 0 to lNewDataSets.Count-1 do begin aListCreatedDatasets.Add(lNewDataSets[i]); end; { for } end; finally FreeAndNil(lNewDatasets); end; end; end.