private void CreateAttacher(ITableInfo t, QueryBuilder qb, LoadMetadata lmd, LoadProgress loadProgressIfAny) { var pt = new ProcessTask(Activator.RepositoryLocator.CatalogueRepository, lmd, LoadStage.Mounting); pt.ProcessTaskType = ProcessTaskType.Attacher; pt.Name = "Read from " + t; pt.Path = typeof(RemoteTableAttacher).FullName; pt.SaveToDatabase(); pt.CreateArgumentsForClassIfNotExists <RemoteTableAttacher>(); pt.SetArgumentValue("RemoteServer", t.Server); pt.SetArgumentValue("RemoteDatabaseName", t.GetDatabaseRuntimeName(LoadStage.PostLoad)); pt.SetArgumentValue("RemoteTableName", t.GetRuntimeName()); pt.SetArgumentValue("DatabaseType", DatabaseType.MicrosoftSQLServer); pt.SetArgumentValue("RemoteSelectSQL", qb.SQL); pt.SetArgumentValue("RAWTableName", t.GetRuntimeName(LoadBubble.Raw)); if (loadProgressIfAny != null) { pt.SetArgumentValue("Progress", loadProgressIfAny); // pt.SetArgumentValue("ProgressUpdateStrategy", DataLoadProgressUpdateStrategy.UseMaxRequestedDay); pt.SetArgumentValue("LoadNotRequiredIfNoRowsRead", true); } /* * * public DataLoadProgressUpdateInfo { get; set; } */ }
/// <summary> /// Returns the reason why <paramref name="table"/> is not refactorable e.g. if it's name is not properly qualified /// with database. Returns null if it is refactorable /// </summary> /// <param name="table"></param> /// <returns></returns> public string GetReasonNotRefactorable(ITableInfo table) { if (string.IsNullOrWhiteSpace(table.Name)) { return("Table has no Name property, this should be the fully qualified database table name"); } if (string.IsNullOrWhiteSpace(table.Database)) { return("Table does not have it's Database property set"); } //ensure database and Name match correctly var syntaxHelper = table.GetQuerySyntaxHelper(); var db = table.GetDatabaseRuntimeName(Curation.Data.DataLoad.LoadStage.PostLoad); if (!table.Name.StartsWith(syntaxHelper.EnsureWrapped(db))) { return(string.Format("Table with Name '{0}' has incorrect database propery '{1}'", table.Name, table.Database)); } if (table.Name != table.GetFullyQualifiedName()) { return(string.Format("Table name '{0}' did not match the expected fully qualified name '{1}'", table.Name, table.GetFullyQualifiedName())); } return(null); }
public void Add(ColumnInfo columnInfo, ITableInfo tableInfo, string databaseName, LoadStage stage, IQuerySyntaxHelper syntaxHelper) { var col = columnInfo.GetRuntimeName(stage); var table = tableInfo.GetRuntimeName(stage); var dbName = tableInfo.GetDatabaseRuntimeName(stage); var snip = new SubstringAutocompleteItem(col); snip.MenuText = col; var fullySpecified = syntaxHelper.EnsureFullyQualified(dbName, tableInfo.Schema, table, col); snip.Text = fullySpecified; snip.Tag = columnInfo; snip.ImageIndex = GetIndexFor(columnInfo, RDMPConcept.ColumnInfo.ToString()); AddUnlessDuplicate(snip); }
public void Add(ITableInfo tableInfo, LoadStage loadStage) { //we already have it or it is not setup properly if (items.Any(i => i.Tag.Equals(tableInfo)) || string.IsNullOrWhiteSpace(tableInfo.Database) || string.IsNullOrWhiteSpace(tableInfo.Server)) { return; } var runtimeName = tableInfo.GetRuntimeName(loadStage); var dbName = tableInfo.GetDatabaseRuntimeName(loadStage); var syntaxHelper = tableInfo.GetQuerySyntaxHelper(); var fullSql = syntaxHelper.EnsureFullyQualified(dbName, null, runtimeName); var snip = new SubstringAutocompleteItem(tableInfo.GetRuntimeName()); snip.MenuText = runtimeName; //name of table snip.Text = fullSql; //full SQL snip.Tag = tableInfo; //record object for future reference snip.ImageIndex = GetIndexFor(tableInfo, RDMPConcept.TableInfo.ToString()); foreach (IHasStageSpecificRuntimeName o in tableInfo.GetColumnsAtStage(loadStage)) { var preDiscarded = o as PreLoadDiscardedColumn; var columnInfo = o as ColumnInfo; if (preDiscarded != null) { Add(preDiscarded, tableInfo, dbName); } else if (columnInfo != null) { Add(columnInfo, tableInfo, dbName, loadStage, syntaxHelper); } else { throw new Exception("Expected IHasStageSpecificRuntimeName returned by TableInfo.GetColumnsAtStage to return only ColumnInfos and PreLoadDiscardedColumns. It returned a '" + o.GetType().Name + "'"); } } AddUnlessDuplicate(snip); }
/// <summary> /// /// </summary> /// <exception cref="SynchronizationFailedException">Could not figure out how to resolve a synchronization problem between the TableInfo and the underlying table structure</exception> /// <param name="notifier">Called every time a fixable problem is detected, method must return true or false. True = apply fix, False = don't - but carry on checking</param> public bool Synchronize(ICheckNotifier notifier) { bool IsSynched = true; //server exists and is accessible? try { _toSyncTo.TestConnection(); } catch (Exception e) { throw new SynchronizationFailedException("Could not connect to " + _toSyncTo, e); } //database exists? var expectedDatabase = _toSyncTo.ExpectDatabase(_tableToSync.GetDatabaseRuntimeName()); if (!expectedDatabase.Exists()) { throw new SynchronizationFailedException("Server did not contain a database called " + _tableToSync.GetDatabaseRuntimeName()); } //identify new columns DiscoveredColumn[] liveColumns; DiscoveredTable expectedTable; if (_tableToSync.IsTableValuedFunction) { expectedTable = expectedDatabase.ExpectTableValuedFunction(_tableToSync.GetRuntimeName(), _tableToSync.Schema); if (!expectedTable.Exists()) { throw new SynchronizationFailedException("Database " + expectedDatabase + " did not contain a TABLE VALUED FUNCTION called " + _tableToSync.GetRuntimeName()); } } else { //table exists? expectedTable = expectedDatabase.ExpectTable(_tableToSync.GetRuntimeName(), _tableToSync.Schema, _tableToSync.IsView ? TableType.View:TableType.Table); if (!expectedTable.Exists()) { throw new SynchronizationFailedException( $"Database {expectedDatabase} did not contain a {(_tableToSync.IsView ? "view" : "table") } called {_tableToSync.GetRuntimeName()} (make sure you have marked whether it is a table/view and that it exists in your database)"); } } try { liveColumns = expectedTable.DiscoverColumns(); } catch (SqlException e) { throw new Exception("Failed to enumerate columns in " + _toSyncTo + " (we were attempting to synchronize the TableInfo " + _tableToSync + " (ID=" + _tableToSync.ID + "). Check the inner exception for specifics", e); } ColumnInfo[] catalogueColumns = _tableToSync.ColumnInfos.ToArray(); IDataAccessCredentials credentialsIfExists = _tableToSync.GetCredentialsIfExists(DataAccessContext.InternalDataProcessing); string pwd = null; string usr = null; if (credentialsIfExists != null) { usr = credentialsIfExists.Username; pwd = credentialsIfExists.GetDecryptedPassword(); } ITableInfoImporter importer; //for importing new stuff if (_tableToSync.IsTableValuedFunction) { importer = new TableValuedFunctionImporter(_repository, (DiscoveredTableValuedFunction)expectedTable); } else { importer = new TableInfoImporter(_repository, _toSyncTo.Name, _toSyncTo.GetCurrentDatabase().GetRuntimeName(), _tableToSync.GetRuntimeName(), _tableToSync.DatabaseType, username: usr, password: pwd, importFromSchema: _tableToSync.Schema, importTableType: _tableToSync.IsView ? TableType.View:TableType.Table); } DiscoveredColumn[] newColumnsInLive = liveColumns.Where( live => !catalogueColumns.Any(columnInfo => columnInfo.GetRuntimeName() .Equals(live.GetRuntimeName()))).ToArray(); //there are new columns in the live database that are not in the Catalogue if (newColumnsInLive.Any()) { //see if user wants to add missing columns bool addMissingColumns = notifier.OnCheckPerformed(new CheckEventArgs("The following columns are missing from the TableInfo:" + string.Join(",", newColumnsInLive.Select(c => c.GetRuntimeName())), CheckResult.Fail, null, "The ColumnInfos will be created and added to the TableInfo")); List <ColumnInfo> added = new List <ColumnInfo>(); if (addMissingColumns) { foreach (DiscoveredColumn missingColumn in newColumnsInLive) { added.Add(importer.CreateNewColumnInfo(_tableToSync, missingColumn)); } ForwardEngineerExtractionInformationIfAppropriate(added, notifier); } else { IsSynched = false; } } //See if we need to delete any ColumnInfos ColumnInfo[] columnsInCatalogueButSinceDisapeared = catalogueColumns .Where(columnInfo => !liveColumns.Any( //there are not any c => columnInfo.GetRuntimeName().Equals(c.GetRuntimeName())) //columns with the same name between discovery/columninfo ).ToArray(); if (columnsInCatalogueButSinceDisapeared.Any()) { foreach (var columnInfo in columnsInCatalogueButSinceDisapeared) { bool deleteExtraColumnInfos = notifier.OnCheckPerformed(new CheckEventArgs("The ColumnInfo " + columnInfo.GetRuntimeName() + " no longer appears in the live table.", CheckResult.Fail, null, "Delete ColumnInfo " + columnInfo.GetRuntimeName())); if (deleteExtraColumnInfos) { columnInfo.DeleteInDatabase(); } else { IsSynched = false; } } } _tableToSync.ClearAllInjections(); if (IsSynched) { IsSynched = SynchronizeTypes(notifier, liveColumns); } if (IsSynched && !_tableToSync.IsTableValuedFunction)//table valued functions don't have primary keys! { IsSynched = SynchronizeField(liveColumns, _tableToSync.ColumnInfos, notifier, "IsPrimaryKey"); } if (IsSynched && !_tableToSync.IsTableValuedFunction)//table valued functions don't have autonum { IsSynched = SynchronizeField(liveColumns, _tableToSync.ColumnInfos, notifier, "IsAutoIncrement"); } if (IsSynched) { IsSynched = SynchronizeField(liveColumns, _tableToSync.ColumnInfos, notifier, "Collation"); } if (IsSynched && _tableToSync.IsTableValuedFunction) { IsSynched = SynchronizeParameters((TableValuedFunctionImporter)importer, notifier); } _tableToSync.ClearAllInjections(); //get list of primary keys from underlying table return(IsSynched); }