Exemple #1
0
        public void GenerateSourceCode()
        {
            var nameSpace = ResolveNameSpace();

            UnsubscribeTablePresenters();
            Task.Factory.StartNew(() =>
            {
                var selectedTables = GetSelectedTables().ToArray();

                var csharp = CodeGeneration.generateCsharp(selectedTables, nameSpace);

                dispatcher.InvokeAsync(() =>
                {
                    SourceCode = csharp;
                });

                SubscribeTablePresenters();
                if (Tables.Any())
                {
                    Document.Tables = Tables
                                      .Select(t => new TableDocument(t.Table.Name, t.Fields.Where(f => f.Selected).Select(f => f.Field.Name).ToArray()))
                                      .ToArray();

                    Document.SelectedTables = selectedTables.Select(t => t.Name).ToArray();
                    documentStorage.Save(Document, Filename);
                }

                SaveGeneratedCode();
            });
        }
Exemple #2
0
 public View AddField(string tableName, Type tableType, AbstractField field, string name = null)
 {
     if (!string.IsNullOrEmpty(tableName) && field != null)
     {
         Table table = null;
         if (Tables != null && Tables.Any() && Tables.Any(x => x.Name == tableName))
         {
             table = Tables.FirstOrDefault(x => x.Name == tableName);
         }
         else
         {
             table = new Table()
             {
                 Name = tableName,
                 Type = tableType
             };
             Tables = (Tables == null) ? new[] { table } : Tables.Concat(new[] { table });
         }
         if (table.Fields == null)
         {
             table.Fields = new Dictionary <string, AbstractField>();
         }
         var fieldName = (!string.IsNullOrEmpty(name)) ? name : field.Name;
         if (!table.Fields.ContainsKey(fieldName))
         {
             field.Table = table;
             table.Fields.Add(fieldName, field);
         }
     }
     return(this);
 }
Exemple #3
0
 public bool Add(string table)
 {
     if (Tables.Any(e => e.Detail == table))
     {
         return(false);
     }
     (Tables as List <DetailTableData>)?.Add(new DetailTableData(table));
     return(true);
 }
        private ArithmeticTaskRequest(IEnumerable <int> tables)
        {
            Tables = tables.ToHashSet();

            if (Tables.Any(x => x < 1 || x > 10))
            {
                throw new ArgumentException("Orders must be between 1 and 10", nameof(tables));
            }
        }
        public void AddTable(Size size, string name = null)
        {
            name = name ?? $"Table{Tables.Count}";

            if (Tables.Any(t => t.Name == name))
            {
                throw new ArgumentException($"Can not create table with duplicate name '{name}'");
            }
            else
            {
                Tables.Add(new Table(name, size.Width, size.Height));

                ActivateTable(Tables.Count - 1);
            }
        }
Exemple #6
0
        public void DetermineParagraphs()
        {
            Paragraphs = new List <Paragraph>();

            var textObjectStatementLines = Statements.Where(_ => _ is TextObjectStatement).Cast <TextObjectStatement>().SelectMany(_ => _.Lines)
                                           .Where(_ => !string.IsNullOrWhiteSpace(_.Content))
                                           .Where(_ => !Tables.Any(t => t.Contains(_.Position.Y)))
                                           .OrderBy(_ => _.Position.Y);

            foreach (var line in textObjectStatementLines)
            {
                if (!Paragraphs.Any(t => t.Contains(line.Position)))
                {
                    Paragraphs.Add(new Paragraph(line.Position.Y));
                }
            }
        }
        public void Setup()
        {
            var file = Path.Combine(TestContext.CurrentContext.TestDirectory, "settings.json");

            if (!File.Exists(file))
            {
                File.WriteAllText(file,
                                  @"{
	""gameId"" : 0,
	""privateKey"" : null,
	""user"" : [""<username>"", ""<token>""],
	""secondUser"" : [""<username>"", ""<token>""],
	""uniqueTable"" : 0,
	""nonUniqueTable"" : 0,
	""tables"" : [0, 0],
	""trophies"" : [
		{""id"":""0"",""difficulty"":""Bronze""},
		{""id"":""0"",""difficulty"":""Silver""},
	]
}
			"            );
            }
            var json = JSONNode.Parse(File.ReadAllText(file));
            var id   = json["gameId"].AsInt;
            var key  = json["privateKey"].Value;

            Credentials       = GetCredentials(json["user"]);
            SecondCredentials = GetCredentials(json["secondUser"]);
            UniqueTable       = json["uniqueTable"].AsInt;
            NonUniqueTable    = json["nonUniqueTable"].AsInt;
            Tables            = json["tables"].ArraySelect(x => new Table(x));
            Trophies          = json["trophies"].ArraySelect(x => new Trophy(x));

            Assert.That(id != 0, "Invalid game id");
            Assert.That(!string.IsNullOrEmpty(key), "Invalid private key");
            Assert.That(UniqueTable != 0, "Invalid test table id");
            Assert.That(NonUniqueTable != 0, "Invalid test table id");
            Assert.That(Tables != null, "Invalid table array");
            Assert.That(Tables.Count >= 2, "Table array must contain at least two table ids");
            Assert.That(Tables.Any(t => t.Id == UniqueTable), "Table array does not contain the test table");
            Assert.That(Tables.Any(t => t.Id == NonUniqueTable), "Table array does not contain the test table");
            Assert.That(Trophies.Count >= 2, "Trophy array must contain at least two trophies");

            Api = new GameJoltApi(id, key);
        }
Exemple #8
0
 public bool Any()
 {
     return(HubVariables.Any() ||
            Datajobs.Any() ||
            Datalinks.Any() ||
            Connections.Any() ||
            Tables.Any() ||
            ColumnValidations.Any() ||
            CustomFunctions.Any() ||
            FileFormats.Any() ||
            RemoteAgentHubs.Any() ||
            DatalinkTests.Any() ||
            Views.Any() ||
            Apis.Any() ||
            Dashboards.Any() ||
            ListOfValues.Any() ||
            Tags.Any() ||
            TagObjects.Any());
 }
        private string BuildFrom()
        {
            if (Tables == null)
            {
                throw new Exception("Tables can not be null.");
            }
            if (!Tables.Any())
            {
                throw new Exception("Tables can not be empty.");
            }

            if (Tables.Any() && Tables.Count() == 1)
            {
                return($"FROM [{Tables.First().Schema}].[{Tables.First().Name}]");
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Exemple #10
0
        public async Task Gettables()
        {
            if (initialized == true)
            {
                IsBusy = true;
                IEnumerable <Table> tables = await tableService.Get();

                // очищаем список
                while (Tables.Any())
                {
                    Tables.RemoveAt(Tables.Count - 1);
                }

                // добавляем загруженные данные
                foreach (Table f in tables)
                {
                    Tables.Add(f);
                }
                IsBusy = false;
            }
            else
            {
                IsBusy = true;
                IEnumerable <Table> tables = await tableService.Get();

                // очищаем список
                while (Tables.Any())
                {
                    Tables.RemoveAt(Tables.Count - 1);
                }

                // добавляем загруженные данные
                foreach (Table f in tables)
                {
                    Tables.Add(f);
                }
                IsBusy      = false;
                initialized = true;
            }
        }
Exemple #11
0
 private bool DetectSingleSchema()
 {
     if (Tables.Any(o => o.Schema != DefaultSchema))
     {
         return(false);
     }
     if (Views.Any(o => o.Schema != DefaultSchema))
     {
         return(false);
     }
     if (StoredProcedures.Any(o => o.Schema != DefaultSchema))
     {
         return(false);
     }
     if (Functions.Any(o => o.Schema != DefaultSchema))
     {
         return(false);
     }
     if (Triggers.Any(o => o.Schema != DefaultSchema))
     {
         return(false);
     }
     return(true);
 }
Exemple #12
0
        public IEnumerable <uint> GetRelatedTables(uint idTable)
        {
            Assert(Tables.Any(t => t.ID == idTable));

            return((GetTable(idTable) as ITableRelation).RelatedTables);
        }
Exemple #13
0
 private bool CanSaveConfigExecute(object sender)
 {
     return(StoredProcs.Any() || Views.Any() || Tables.Any());
 }
 public bool HasTable(string name)
 {
     return(Tables.Any(t => t.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)));
 }
Exemple #15
0
        internal void ValidateAndAdjust()
        {
            // Connection string
            if (ConnectionString == null)
            {
                // ReSharper disable once NotResolvedInText
                throw new ArgumentNullException("SqlDependencyProvider.Parameters.ConnectionString");
            }

            // Tables
            var tableInfos = new List <SqlDependencyQualifiedObjectName>(Tables);

            tableInfos = tableInfos
                         .Where(p => p?.Name != null)
                         .Distinct()
                         .ToList();
            if (tableInfos.Count == 0)
            {
                // ReSharper disable once NotResolvedInText
                throw new ArgumentNullException("SqlDependencyProvider.Parameters.Tables");
            }
            Tables.Clear();
            Tables.AddRange(tableInfos.OrderBy(p => p.Schema, StringComparer.OrdinalIgnoreCase)
                            .ThenBy(p => p.Name, StringComparer.OrdinalIgnoreCase));

            // Monitored changes
            if (MonitoredChanges == SqlDependencyMonitoredChanges.None)
            {
                // ReSharper disable once NotResolvedInText
                throw new ArgumentNullException("SqlDependencyProvider.Parameters.MonitoredChanges");
            }

            // Check all monitored tables exist
            using (var conn = new SqlConnection(ConnectionString))
            {
                // Ensure open
                Helper.EnsureOpenConnection(conn);

                // Check
                var nonExistingTableNames = new List <string>();
                if (!Tables.Any(t =>
                {
                    if (!Helper.TableExists(conn, null, t))
                    {
                        nonExistingTableNames.Add(t.ToString());
                        return(false);
                    }
                    return(true);
                }))
                {
#if USETRANSLATIONS
                    throw new InvalidOperationException(
                              Translations.Default["SText_SqlDependencyOneOrMoreMonitoredTablesDoNotExist_Names",
                                                   string.Join(", ", nonExistingTableNames)]);
#else
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                      Resources.SText_SqlDependencyOneOrMoreMonitoredTablesDoNotExist_Names,
                                                                      string.Join(", ", nonExistingTableNames)));
#endif
                }
            }
        }
Exemple #16
0
        /// <summary>
        /// Parses the data operations generating the underlying SQL.
        /// </summary>
        private void Parse()
        {
            if (DbTables == null)
            {
                throw new InvalidOperationException("RegisterDatabase must be invoked before parsing can occur.");
            }

            // Get the identifier generator configuration where applicable.
            var idjson = _json["^Type"];

            if (idjson != null)
            {
                var typeName = idjson.ToObject <string>();
                if (string.IsNullOrEmpty(typeName))
                {
                    throw new SqlDataUpdaterException($"Identifier generators property '^Type' is not a valid string.");
                }

                var type = Type.GetType(typeName, false);
                if (type == null || type.GetConstructor(Array.Empty <Type>()) == null)
                {
                    throw new SqlDataUpdaterException($"Identifier generators Type '{typeName}' does not exist or have a default (parameter-lesss) constructor.");
                }

                var idgen = Activator.CreateInstance(type) !;
                IdentifierGenerators = idgen as IIdentifierGenerators;
                if (IdentifierGenerators == null)
                {
                    throw new SqlDataUpdaterException($"Identifier generators Type '{typeName}' does not implement IIdentifierGenerators.");
                }
            }

            // Loop through all the schemas.
            foreach (var js in _json.Children <JProperty>())
            {
                // Reserved; ignore.
                if (js.Name == "^Type")
                {
                    continue;
                }

                // Loop through the collection of tables.
                foreach (var jto in GetChildObjects(js))
                {
                    foreach (var jt in jto.Children <JProperty>())
                    {
                        var sdt = new SqlDataTable(js.Name, jt.Name);
                        if (Tables.Any(t => t.Schema == sdt.Schema && t.Name == sdt.Name))
                        {
                            throw new SqlDataUpdaterException($"Table '{sdt.Schema}.{sdt.Name}' has been specified more than once.");
                        }

                        // Loop through the collection of rows.
                        foreach (var jro in GetChildObjects(jt))
                        {
                            var row = new SqlDataRow(sdt);

                            foreach (var jr in jro.Children <JProperty>())
                            {
                                if (jr.Value.Type == JTokenType.Object)
                                {
                                    foreach (var jc in jro.Children <JProperty>())
                                    {
                                        var col = sdt.IsRefData ? DatabaseRefDataColumns.CodeColumnName : sdt.DbTable.Columns.Where(x => x.IsPrimaryKey).Select(x => x.Name).SingleOrDefault();
                                        if (!string.IsNullOrEmpty(col))
                                        {
                                            row.AddColumn(col, GetColumnValue(jc.Name));
                                            foreach (var jcv in jc.Values().Where(j => j.Type == JTokenType.Property).Cast <JProperty>())
                                            {
                                                row.AddColumn(jcv.Name, GetColumnValue(jcv.Value));
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    if (sdt.IsRefData && jro.Children().Count() == 1)
                                    {
                                        row.AddColumn(DatabaseRefDataColumns.CodeColumnName, GetColumnValue(jr.Name));
                                        row.AddColumn("Text", GetColumnValue(jr.Value));
                                    }
                                    else
                                    {
                                        row.AddColumn(jr.Name, GetColumnValue(jr.Value));
                                    }
                                }
                            }

                            sdt.AddRow(row);
                        }

                        if (sdt.Columns.Count > 0)
                        {
                            sdt.Prepare(IdentifierGenerators);
                            Tables.Add(sdt);
                        }
                    }
                }
            }
        }
Exemple #17
0
 public bool IsChild(ISqlTableSource table)
 {
     return(Tables.Any(ts => ts.Source == table || CheckChild(ts.Joins, table)));
 }
Exemple #18
0
        /// <summary>
        /// Determines the table structures.
        /// </summary>
        public void DetermineTableStructures()
        {
            JoinedLines = JoinLines(AllLines);

            // Find table borders
            foreach (Line horizontalLine in JoinedHorizontalLines.OrderBy(_ => _.StartPoint.Y))
            {
                // We consider that this line is a top line of a table if
                // 1. There is not a table with this line inside
                // 2. There is a vertical line starting from this line

                if (Tables.Any(_ => _.Contains(horizontalLine.StartPoint.Y)))
                {
                    continue;
                }

                Line?tableLine = JoinedVerticalLines
                                 .Where(_ => _.StartPoint == horizontalLine.StartPoint || _.StartPoint == horizontalLine.EndPoint)
                                 .OrderByDescending(_ => _.EndPoint.Y - _.StartPoint.Y)
                                 .Cast <Line?>()
                                 .FirstOrDefault();

                if (tableLine == null)
                {
                    continue;
                }

                Table tableStructure = new Table()
                {
                    TopLeftPoint     = horizontalLine.StartPoint,
                    BottomRightPoint = new Point(horizontalLine.EndPoint.X, tableLine.Value.EndPoint.Y)
                };

                Tables.Add(tableStructure);
            }

            // Add the first row and the first column to all tables
            foreach (Table tableStructure in Tables)
            {
                tableStructure.Rows.Add(new Row()
                {
                    BeginY = tableStructure.TopLeftPoint.Y
                });
                tableStructure.Columns.Add(new Column()
                {
                    BeginX = tableStructure.TopLeftPoint.X
                });
            }

            // Find rows
            foreach (Line horizontalLine in JoinedHorizontalLines.OrderBy(_ => _.StartPoint.Y))
            {
                var tableStructure = Tables.FirstOrDefault(_ => _.Contains(horizontalLine));
                // No table contains this line
                if (tableStructure == null)
                {
                    continue;
                }

                // Check if the row already belongs to the table
                if (tableStructure.Rows.Any(_ => Math.Abs(_.BeginY - horizontalLine.StartPoint.Y) < ContentExtractor.Tolerance))
                {
                    continue;
                }

                // Check if the row is the bottom edge of the table
                if (tableStructure.BottomRightPoint.Y - horizontalLine.StartPoint.Y < ContentExtractor.Tolerance)
                {
                    continue;
                }

                tableStructure.Rows.Add(new Row()
                {
                    BeginY = horizontalLine.StartPoint.Y
                });
            }

            // Find columns
            foreach (Line verticalLine in JoinedVerticalLines.OrderBy(_ => _.StartPoint.X))
            {
                var tableStructure = Tables.FirstOrDefault(_ => _.Contains(verticalLine));
                // No table contains this line
                if (tableStructure == null)
                {
                    continue;
                }

                // The row already belongs to the table
                if (tableStructure.Columns.Any(_ => Math.Abs(_.BeginX - verticalLine.StartPoint.X) < ContentExtractor.Tolerance))
                {
                    continue;
                }

                // Check if the row is the bottom edge of the table
                if (tableStructure.BottomRightPoint.X - verticalLine.StartPoint.X < ContentExtractor.Tolerance)
                {
                    continue;
                }


                tableStructure.Columns.Add(new Column()
                {
                    BeginX = verticalLine.StartPoint.X
                });
            }


            // Fix EndX and EndY and indexes
            foreach (Table tableStructure in Tables)
            {
                // Fix EndYs
                for (int i = 0; i < tableStructure.Rows.Count - 1; i++)
                {
                    tableStructure.Rows[i].EndY = tableStructure.Rows[i + 1].BeginY - ContentExtractor.Tolerance * 0.1f;
                }

                tableStructure.Rows[tableStructure.Rows.Count - 1].EndY = tableStructure.BottomRightPoint.Y;


                // Fix EndXs
                for (int i = 0; i < tableStructure.Columns.Count - 1; i++)
                {
                    tableStructure.Columns[i].EndX = tableStructure.Columns[i + 1].BeginX - ContentExtractor.Tolerance * 0.1f;
                }

                tableStructure.Columns[tableStructure.Columns.Count - 1].EndX = tableStructure.BottomRightPoint.X;

                int index;

                index = 0;
                foreach (var column in tableStructure.Columns.OrderBy(_ => _.BeginX))
                {
                    column.Index = index;
                    index++;
                }

                index = 0;
                foreach (var row in tableStructure.Rows.OrderByDescending(_ => _.BeginY))
                {
                    row.Index = index;
                    index++;
                }

                tableStructure.CreateContent();
            }
        }
Exemple #19
0
 public bool HasAggregateFields()
 {
     return(Tables?.Any(x => x?.HasAggregateFields() ?? false) ?? false);
 }
 public bool IncludeViews()
 {
     return(Tables.Any());
 }
Exemple #21
0
        public void FinishedBuilding()
        {
            if (!Tables.Any())
            {
                return;
            }

            // Set the global relations
            Relations = Tables.SelectMany(t => t.ForeignKeys).ToArray();

            // Sort the tables in topological order
            Tables = SortTopologically(Tables, false).ToArray();
            for (int i = 0; i < Tables.Length; i++)
            {
                Tables[i].TopologicalOrder = i;
            }


            // Sort the table unique constraints in order
            Tables.ForEach(table =>
                           table.UniqueConstraints = (
                               from uniqueConstraint in table.UniqueConstraints
                               let minColumnIndex = (from column in table.Columns where column.Name.IsIn(uniqueConstraint.Columns) select column.Position).Min()
                                                    orderby minColumnIndex ascending
                                                    select uniqueConstraint
                               ).ToArray()
                           );

            // Sort the table foreign keys in order
            Tables.ForEach(table =>
                           table.ForeignKeys = (
                               from foreignKey in table.ForeignKeys
                               let minColumnIndex = (from column in table.Columns where column.Name.IsIn(foreignKey.ForeignKeyColumns) select column.Position).Min()
                                                    orderby minColumnIndex ascending
                                                    select foreignKey
                               ).ToArray()
                           );


            // Set convenience properties
            Tables.ForEach(table => {
                table.Owner       = this;
                table.Columns     = (from col in table.Columns orderby col.Position ascending select col).ToArray();
                table.ColumnIndex = (from col in table.Columns.WithDescriptions() select col).ToDictionary(x => x.Item.Name, x => x.Index);
                if (table.PrimaryKey != null)
                {
                    table.PrimaryKeyColumns = (from pk in table.PrimaryKey.ColumnNames select table.Columns[table.ColumnIndex[pk]]).ToArray();
                }
                table.BlobColumns = (from col in table.Columns where col.Type == typeof(byte[]) select col).ToArray();

                #region Set Column owner
                table.Columns.ForEach(c => c.Owner = table);
                #endregion

                #region Set if a primary key is also a foreign key
                if (table.PrimaryKey != null)
                {
                    table.PrimaryKey.ColumnsAlsoForeignKeys = table.PrimaryKeyColumns.Any(c => c.IsForeignKey);
                    if (table.PrimaryKey.KeyType.HasFlag(DBKeyType.Artificial))
                    {
                        table.PrimaryKeyColumns.ForEach(c => c.KeyType = c.KeyType.SetFlags(DBKeyType.Artificial));
                    }
                }
                #endregion

                #region Set the Sequence/Generator
                if (table.PrimaryKey != null)
                {
                    if (!string.IsNullOrEmpty(table.PrimaryKey.Sequence))
                    {
                        table.PrimaryKeyColumns.Single().Sequence = table.PrimaryKey.Sequence;
                    }
                }
                #endregion

                #region Set if Foreign Key is to a constraint or a primary key
                foreach (var foreignKeyDescription in table.ForeignKeys.WithDescriptions())
                {
                    foreignKeyDescription.Item.Position = foreignKeyDescription.Index;

                    var referenceTable    = this[foreignKeyDescription.Item.ReferenceTable];
                    var referenceColumns  = referenceTable.Columns.Where(c => c.Name.IsIn(foreignKeyDescription.Item.ReferenceColumns));
                    var foreignKeyColumns = table.Columns.Where(c => c.Name.IsIn(foreignKeyDescription.Item.ForeignKeyColumns));
                    if (referenceColumns.Any(c => !c.IsPrimaryKey))
                    {
                        foreignKeyDescription.Item.ReferenceIsUniqueConstraint = true;
                    }
                    else
                    {
                        foreignKeyDescription.Item.ReferenceIsUniqueConstraint = false;
                    }

                    foreignKeyDescription.Item.ReferenceTablePrimaryKey = referenceTable.PrimaryKey.ColumnNames;

                    if (foreignKeyDescription.Item.KeyType.HasFlag(DBKeyType.Artificial))
                    {
                        foreignKeyColumns.ForEach(c => c.KeyType = c.KeyType.SetFlags(DBKeyType.Artificial));
                    }
                }
                #endregion

                #region Set Unique Constraint Properties
                foreach (var uniqueConstraintDescription in table.UniqueConstraints.WithDescriptions())
                {
                    var uniqueConstraintColumns = table.Columns.Where(c => c.Name.IsIn(uniqueConstraintDescription.Item.Columns));
                    uniqueConstraintDescription.Item.Position = uniqueConstraintDescription.Index;
                    uniqueConstraintDescription.Item.ColumnsAlsoForeignKey = uniqueConstraintColumns.Any(c => c.IsForeignKey);

                    if (uniqueConstraintDescription.Item.KeyType.HasFlag(DBKeyType.Artificial))
                    {
                        uniqueConstraintColumns.ForEach(c => c.KeyType = c.KeyType.SetFlags(DBKeyType.Artificial));
                    }
                }
                #endregion

                // Determine the primary key type
                var primaryKey = table.PrimaryKey;
                if (primaryKey != null)
                {
                    if (primaryKey.ColumnNames.Length == 1)
                    {
                        var pkCol = table.GetColumn(primaryKey.ColumnNames[0]);
                        if (pkCol.IsAutoIncrement)
                        {
                            primaryKey.KeyType = primaryKey.KeyType.SetFlags(DBKeyType.AutoCalculated);
                        }
                        else if (pkCol.UsesSequence)
                        {
                            primaryKey.KeyType = primaryKey.KeyType.SetFlags(DBKeyType.Sequenced);
                        }
                        else if (table.PrimaryKeyColumns.Length == 1 && pkCol.Type.IsIntegerNumeric())
                        {
                            primaryKey.KeyType = primaryKey.KeyType.SetFlags(DBKeyType.ManuallyAssignedSingleInt);
                        }
                    }

                    foreach (var primaryKeyColumnName in primaryKey.ColumnNames)
                    {
                        var primaryKeyColumn     = table.GetColumn(primaryKeyColumnName);
                        primaryKeyColumn.KeyType = primaryKeyColumn.KeyType.SetFlags(primaryKey.KeyType);
                    }
                }
            });

            // Determine the foreign key types and nullability
            Tables.ForEach(table => {
                foreach (var foreignKey in table.ForeignKeys)
                {
                    if (foreignKey.ForeignKeyColumns.Length != foreignKey.ReferenceColumns.Length)
                    {
                        throw new Exception(string.Format("Foreign key '{0}' in table '{1}' is malformed, inconsistent columns specified for primary key table"));
                    }

                    ////////////// Is this really necessary ?
                    if (foreignKey.ReferenceColumns.Length == 1)
                    {
                        var pkTable = this[foreignKey.ReferenceTable];
                        var pkCol   = pkTable.GetColumn(foreignKey.ReferenceColumns[0]);
                        if (pkCol.IsAutoIncrement)
                        {
                            foreignKey.KeyType = foreignKey.KeyType.SetFlags(DBKeyType.AutoCalculated);
                        }
                        else if (pkCol.UsesSequence)
                        {
                            foreignKey.KeyType = foreignKey.KeyType.SetFlags(DBKeyType.Sequenced);
                        }
                        else if (pkTable.PrimaryKeyColumns.Length == 1 && pkCol.Type.IsIntegerNumeric())
                        {
                            foreignKey.KeyType = foreignKey.KeyType.SetFlags(DBKeyType.ManuallyAssignedSingleInt);
                        }
                    }
                    //////////////

                    foreach (var col in foreignKey.ForeignKeyColumns)
                    {
                        var foreignKeyColumn     = table.GetColumn(col);
                        foreignKeyColumn.KeyType = foreignKeyColumn.KeyType.SetFlags(foreignKey.KeyType);
                    }
                    foreignKey.IsNullable = foreignKey.ForeignKeyColumns.All(c => table[c].IsNullable);
                }
            });

            // Now go through and determine the roots
            Tables.ForEach(table => {
                table.KeyRoots =
                    table
                    .Columns
                    .Where(column => column.IsPrimaryKey || column.IsForeignKey)
                    .Select(
                        column => {
                    var keyRoot = FindKeyRootRecursively(table, column);

                    if (keyRoot.IsAutoIncrement)
                    {
                        column.KeyType = column.KeyType.SetFlags(DBKeyType.RootIsAutoCalculated);
                    }

                    if (keyRoot.UsesSequence)
                    {
                        column.KeyType = column.KeyType.SetFlags(DBKeyType.RootIsSequenced);
                    }

                    if (this[keyRoot.RootTable][keyRoot.RootColumn].KeyType.HasFlag(DBKeyType.ManuallyAssignedSingleInt))
                    {
                        column.KeyType = column.KeyType.SetFlags(DBKeyType.RootIsManuallyAssignedSingleInt);
                    }

                    return(new {
                        ColumnName = column.Name,
                        KeyRoot = keyRoot
                    });
                }
                        )
                    .ToDictionary(x => x.ColumnName, x => x.KeyRoot);
            });

            // Calculate the height
            Tables.ForEach(t => CalculateHeight(t));

            MaxHeight = Tables.Select(t => t.Height).Max();
        }