示例#1
0
        public override void FromJson(JObject json, DcSpace ws)
        {
            base.FromJson(json, ws); // Table

            RelationalTableName = (string)json["RelationalTableName"];
            RelationalPkName    = (string)json["RelationalPkName"];

            // List of greater paths (relational attributes)
            if (json["greater_paths"] != null)
            {
                if (GreaterPaths == null)
                {
                    GreaterPaths = new List <ColumnAtt>();
                }
                foreach (JObject greater_path in json["greater_paths"])
                {
                    ColumnAtt path = (ColumnAtt)Utils.CreateObjectFromJson(greater_path);
                    if (path != null)
                    {
                        path.FromJson(greater_path, ws);
                        GreaterPaths.Add(path);
                    }
                }
            }
        }
示例#2
0
        public void AddAllNonStoredPaths()
        {
            // The method adds entity (non-PK) columns from referenced (by FK) tables (recursively).
            int pathCounter = 0;

            ColumnAtt      path      = new ColumnAtt("");
            PathEnumerator primPaths = new PathEnumerator(this, ColumnType.IDENTITY_ENTITY);

            foreach (ColumnAtt p in primPaths)
            {
                if (p.Size < 2)
                {
                    continue;             // All primitive paths are stored in this set. We need at least 2 segments.
                }
                // Check if this path already exists
                path.Segments = p.Segments;
                if (GetGreaterPath(path) != null)
                {
                    continue;                               // Already exists
                }
                string pathName = "__inherited__" + ++pathCounter;

                ColumnAtt newPath = new ColumnAtt(pathName);
                newPath.Segments             = new List <DcColumn>(p.Segments);
                newPath.RelationalColumnName = newPath.Name;          // It actually will be used for relational queries
                newPath.RelationalFkName     = path.RelationalFkName; // Belongs to the same FK
                newPath.RelationalPkName     = null;
                //newPath.Input = this;
                //newPath.Output = p.Path[p.Length - 1].Output;

                AddGreaterPath(newPath);
            }
        }
示例#3
0
 public ColumnAtt GetGreaterPath(ColumnAtt path)
 {
     if (path == null || path.Segments == null)
     {
         return(null);
     }
     return(GetGreaterPath(path.Segments));
 }
示例#4
0
 public List <ColumnAtt> GetGreaterPathsStartingWith(ColumnAtt path)
 {
     if (path == null || path.Segments == null)
     {
         return(new List <ColumnAtt>());
     }
     return(GetGreaterPathsStartingWith(path.Segments));
 }
示例#5
0
        public void RemoveGreaterPath(string name)
        {
            ColumnAtt path = GetGreaterPath(name);

            if (path != null)
            {
                RemoveGreaterPath(path);
            }
        }
示例#6
0
        /// <summary>
        /// Expand one attribute by building its path segments as dimension objects.
        /// Use the provided list of attributes for expansion recursively. This list essentially represents a schema.
        /// Also, adjust path names in special cases like empty name or simple structure.
        /// </summary>
        public void ExpandAttribute(List <ColumnAtt> attributes, List <DcColumn> columns) // Add and resolve attributes by creating dimension structure from FKs
        {
            ColumnAtt att = this;

            if (att.Segments.Count > 0)
            {
                return;                         // Already expanded (because of recursion)
            }
            bool isKey = !string.IsNullOrEmpty(att.RelationalPkName) || att.IsKey;

            if (string.IsNullOrEmpty(att.RelationalFkName)) // No FK - primitive column - end of recursion
            {
                // Find or create a primitive dim segment
                DcColumn seg = columns.FirstOrDefault(c => c.Input == att.Input && StringSimilarity.SameColumnName(((ColumnRel)c).RelationalFkName, att.RelationalFkName));
                if (seg == null)
                {
                    seg = new ColumnRel(att.RelationalColumnName, att.Input, att.Output, isKey, false); // Maybe copy constructor?
                    ((ColumnRel)seg).RelationalFkName = att.RelationalFkName;
                    columns.Add(seg);
                }

                att.InsertLast(seg); // add it to this attribute as a single segment
            }
            else
            { // There is FK - non-primitive column
                // Find target set and target attribute (name resolution)
                ColumnAtt tailAtt = attributes.FirstOrDefault(a => StringSimilarity.SameTableName(a.Input.Name, att.RelationalTargetTableName) && StringSimilarity.SameColumnName(a.Name, att.RelationalTargetColumnName));
                DcTable   gTab    = tailAtt.Input;

                // Find or create a dim segment
                DcColumn seg = columns.FirstOrDefault(c => c.Input == att.Input && StringSimilarity.SameColumnName(((ColumnRel)c).RelationalFkName, att.RelationalFkName));
                if (seg == null)
                {
                    seg = new ColumnRel(att.RelationalFkName, att.Input, gTab, isKey, false);
                    ((ColumnRel)seg).RelationalFkName = att.RelationalFkName;
                    columns.Add(seg);
                }

                att.InsertLast(seg); // add it to this attribute as first segment

                //
                // Recursion. Expand tail attribute and add all segments from the tail attribute (continuation)
                //
                tailAtt.ExpandAttribute(attributes, columns);
                att.InsertLast(tailAtt);

                // Adjust name. How many attributes belong to the same FK as this attribute (FK composition)
                List <ColumnAtt> fkAtts = attributes.Where(a => a.Input == att.Input && StringSimilarity.SameColumnName(att.RelationalFkName, a.RelationalFkName)).ToList();
                if (fkAtts.Count == 1)
                {
                    seg.Name = att.RelationalColumnName; // Adjust name. For 1-column FK, name of the FK-dim is the column name (not the FK name)
                }
            }
        }
示例#7
0
 public void RemoveGreaterPath(ColumnAtt path)
 {
     Debug.Assert(path.Output != null && path.Input != null, "Wrong use: path must specify a lesser and greater sets before it can be removed from a set.");
     if (path.Output is TableRel)
     {
         ((TableRel)path.Output).LesserPaths.Remove(path);
     }
     if (path.Input is TableRel)
     {
         ((TableRel)path.Input).GreaterPaths.Remove(path);
     }
 }
示例#8
0
//
// What is Set::AddAllNonStoredPaths() ???
//

/*
 *      public void ImportSchema(List<string> tableNames = null)
 *      {
 *          if (tableNames == null)
 *          {
 *              tableNames = connection.ReadTables();
 *          }
 *
 *          // Create all sets
 *          foreach (string tableName in tableNames)
 *          {
 *              Set set = new Set(tableName); // Create a set
 *              set.RelationalTableName = tableName;
 *              this.AddTable(set, null);
 *          }
 *
 *          // Load columns and FKs as (complex) paths and (simple) FK-dimensions
 *          foreach (string tableName in tableNames)
 *          {
 *              ImportPaths(tableName);
 *          }
 *
 *          List<ComTable> sets = Root.GetAllSubsets();
 *          foreach (ComTable set in sets)
 *          {
 *              foreach (DimPath path in set.GreaterPaths)
 *              {
 *                  path.ExpandPath();
 *              }
 *          }
 *
 *          foreach (Set set in sets)
 *          {
 *              set.AddAllNonStoredPaths();
 *          }
 *      }
 */

        protected List <ColumnAtt> LoadAttributes(TableRel table)
        {
            // The created paths will be not be added to the schema (should be added manually)
            // The created paths are empty and do not store any dimensions (should be done/expanded separately by using the meta-data about PKs, FKs etc.)
            Debug.Assert(!table.IsPrimitive, "Wrong use: cannot load structure for primitive set.");

            List <ColumnAtt> attributes = new List <ColumnAtt>();

            string tableName = table.RelationalTableName;

            DataTable pks     = connection.GetPks(tableName);
            DataTable fks     = connection.GetFks(tableName);
            DataTable columns = connection.GetColumns(tableName);

            foreach (DataRow col in columns.Rows) // Process all columns of the table (correspond to primitive paths of the set)
            {
                string  columnName = col["COLUMN_NAME"].ToString();
                string  columnType = ((OleDbType)col["DATA_TYPE"]).ToString();
                DcTable typeTable  = Schema.GetPrimitiveType(columnType);

                //
                // Create an attribute object representing this column
                //
                ColumnAtt path = table.GetGreaterPathByColumnName(columnName); // It might have been already created (when processing other tables)
                if (path != null)
                {
                    continue;
                }

                path = new ColumnAtt(columnName, table, typeTable);

                //
                // Set relational attribute of the object
                //

                path.RelationalColumnName = columnName;

                // Find PKs this attribute belongs to (among all PKs of this table)
                foreach (DataRow pk in pks.Rows)
                {
                    if (!StringSimilarity.SameColumnName(columnName, (string)pk["COLUMN_NAME"]))
                    {
                        continue;
                    }

                    // Found PK this column belongs to
                    path.RelationalPkName  = (string)pk["PK_NAME"];
                    table.RelationalPkName = path.RelationalPkName; // OPTIMIZE: try to do it only once rather than for each attribute and try to identify and exclude multiple PKs (error)

                    //path.IsIdentity = true; // We simply have to override this property as "RelationalPkName != null" or "RelationalPkName == table.RelationalPkName"
                    break; // Assume that a column can belong to only one PK
                }

                // Find FKs this attribute belongs to (among all FKs of this table)
                foreach (DataRow fk in fks.Rows)
                {
                    if (!StringSimilarity.SameColumnName(columnName, (string)fk["FK_COLUMN_NAME"]))
                    {
                        continue;
                    }

                    // Target PK name fk["PK_NAME"] is not stored and is not used because we assume that there is only one PK

                    path.RelationalFkName           = (string)fk["FK_NAME"];
                    path.RelationalTargetTableName  = (string)fk["PK_TABLE_NAME"];  // Name of the target set of the simple dimension (first segment of this complex path)
                    path.RelationalTargetColumnName = (string)fk["PK_COLUMN_NAME"]; // Next path/attribute name belonging to the target set

                    break;                                                          // We assume that a column can belong to only one FK and do not continue with the rest of the FK-loop
                }

                attributes.Add(path);
            }

            return(attributes);
        }