Beispiel #1
0
 public ColumnAtt GetGreaterPath(List <DcColumn> path)
 {
     if (path == null)
     {
         return(null);
     }
     foreach (ColumnAtt p in GreaterPaths)
     {
         if (p.Segments == null)
         {
             continue;
         }
         if (p.Segments.Count != path.Count)
         {
             continue;                                 // Different lengths => not equal
         }
         bool equal = true;
         for (int seg = 0; seg < p.Segments.Count && equal; seg++)
         {
             if (!StringSimilarity.SameColumnName(p.Segments[seg].Name, path[seg].Name))
             {
                 equal = false;
             }
             // if (p.Path[seg] != path[seg]) equal = false; // Compare strings as objects
         }
         if (equal)
         {
             return(p);
         }
     }
     return(null);
 }
Beispiel #2
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)
                }
            }
        }
Beispiel #3
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);
        }
Beispiel #4
0
 public ColumnAtt GetGreaterPathByColumnName(string name)
 {
     return(GreaterPaths.FirstOrDefault(d => StringSimilarity.SameColumnName(d.RelationalColumnName, name)));
 }
Beispiel #5
0
        }                                            // Note that the same field exists also in Dim

        public DcColumn GetGreaterColByFkName(string name)
        {
            return(Columns.FirstOrDefault(d => StringSimilarity.SameColumnName(((ColumnRel)d).RelationalFkName, name)));
        }