Exemple #1
0
        public override void BuildFrom(
            SelectQuery query,
            List <ReportColumnMapping> selectedColumns,
            ReportColumnMapping groupByColumn,
            ReportColumnMapping sortByColumn,
            MappedSearchRequest request)
        {
            // idea here is to be able to get a key which can be joined on, so select from the table we're building the CTE from
            // then join on the tables required to get to the join key (which can be used as the group key)

            _rootTableName = request.GroupByColumn.KnownTable;
            var fromTable = _tableMappings.GetTableMapping(_fromTableName);

            var addedTables = new List <string>();

            if (CanJoinTables(_fromTableName, _rootTableName))
            {
                query.From(fromTable.DbTableName, fromTable.Alias);
            }
            else
            {
                var graphBuilder      = new TableRelationshipGraphBuilder();
                var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _rootTableName);

                // todo : use path
                //var path = graphBuilder.GetPathFromTableToRoot(relationshipGraph, _fromTableName);

                var distance = graphBuilder.GetDistance(relationshipGraph, _fromTableName);

                query.From(fromTable.DbTableName, fromTable.Alias);

                string currentTableName = fromTable.KnownTableName;
                while (distance > 1)
                {
                    var potentialNodes = graphBuilder.GetByDistance(relationshipGraph, distance - 1);
                    var parentNode     = potentialNodes.SingleOrDefault(x => x.Relations.Any(y => y.TableName == currentTableName));
                    if (parentNode == null)
                    {
                        throw new Exception(string.Format("Could not find a relationship between {0} and {1}", currentTableName, relationshipGraph.TableName));
                    }
                    JoinTables(query, parentNode.TableName, currentTableName);
                    currentTableName = parentNode.TableName;
                    distance--;
                    addedTables.Add(parentNode.TableName);
                    if (CanJoinTables(_fromTableName, currentTableName) && CanJoinTables(currentTableName, _rootTableName))
                    {
                        break;
                    }
                }
            }
        }
Exemple #2
0
        public TableInfo GetTableInfo()
        {
            var relations    = _tableMappings.GetAllTableRelationships();
            var graphBuilder = new TableRelationshipGraphBuilder();
            var graph        = graphBuilder.Build(relations, _constants.RootTableName);
            var tables       = _tableMappings.GetAllTables();

            tables = tables.OrderBy(x => graphBuilder.GetDistance(graph, x.KnownTableName)).ToList();

            return(new TableInfo
            {
                Tables = tables,
                Relationships = relations
            });
        }
        // Build
        public override void BuildFrom(
            SelectQuery query,
            List <ReportColumnMapping> selectedColumns,
            ReportColumnMapping groupByColumn,
            ReportColumnMapping sortByColumn,
            MappedSearchRequest request)
        {
            var statsRelationships = _tableMappings.GetAllTableRelationships()
                                     .Where(x => x.Table1 is StatsTableMapping || x.Table2 is StatsTableMapping)
                                     .ToList();


            // get the data table which joins onto the stats table
            var graphBuilder  = new TableRelationshipGraphBuilder();
            var dataJoinTable = _dataSourceComponents.StatsQueryBuilder.GetDataJoinTable(request.GroupByColumn, statsRelationships, graphBuilder);

            //-- Find out which stats table or view we need to query to satisfy the requested temporal
            // aggregation and type of date range.
            var statsTableName = GetStatsTableName(
                _statsTableName,
                dataJoinTable,
                request.TemporalAggregation,
                request.DateRangeType,
                request.DateStart,
                request.DateEnd);

            query.From(statsTableName, _statsTableAlias);
            JoinTables(query, dataJoinTable, _statsTableName);

            // join up to the root table
            var addedTables = new Dictionary <string, bool> {
                { dataJoinTable, false }
            };

            _dataSourceComponents.StatsQueryBuilder.AddDataTableJoinsUpToRoot(query, dataJoinTable, graphBuilder, addedTables);

            var currencyColumn = GetCurrencyColumn();

            if (currencyColumn != null && !addedTables.ContainsKey(currencyColumn.KnownTable))
            {
                var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _constants.RootTableName);
                AddFromTableJoin(query, groupByColumn, currencyColumn.KnownTable, ref addedTables, graphBuilder, relationshipGraph);
            }
        }
Exemple #4
0
        public virtual void BuildFrom(
            SelectQuery query,
            List <ReportColumnMapping> selectedColumns,
            ReportColumnMapping groupByColumn,
            ReportColumnMapping sortByColumn,
            MappedSearchRequest request)
        {
            var tables = request.SelectedAndDependantColumns.Select(x => x.KnownTable).ToList();

            tables.Add(groupByColumn.KnownTable);
            tables = tables.Distinct().ToList();

            var currencyColumn = GetCurrencyColumn();

            if (currencyColumn != null && !tables.Contains(currencyColumn.KnownTable))
            {
                tables.Add(currencyColumn.KnownTable);
            }

            var rootTableMapping = _tableMappings.GetTableMapping(_constants.RootTableName);

            query.From(rootTableMapping.DbTableName, rootTableMapping.Alias);

            var graphBuilder = new TableRelationshipGraphBuilder();
            // bulild a graph of the table relationships to calculate the distance from the root table
            // include missing tables needed for joins
            // order the tables by distance
            var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _constants.RootTableName);

            graphBuilder.TrimToTables(relationshipGraph, tables);
            tables = graphBuilder.GetAllTables(relationshipGraph).Union(tables).Distinct().ToList();

            tables = tables.OrderBy(x => graphBuilder.GetDistance(relationshipGraph, x)).ToList();

            // dictionary of TableName, IsAggregated for tables which have been added to the query
            var addedTables = new Dictionary <string, bool> {
                { _constants.RootTableName, false }
            };

            foreach (var table in tables.Distinct())
            {
                AddFromTableJoin(query, groupByColumn, table, ref addedTables, graphBuilder, relationshipGraph);
            }
        }
        protected override ReportColumnMapping RestrictGroupBy(MappedSearchRequest request)
        {
            var statsRelationships = _tableMappings.GetAllTableRelationships()
                                     .Where(x => x.Table1 is StatsTableMapping || x.Table2 is StatsTableMapping)
                                     .ToList();


            // get the data table which joins onto the stats table
            var graphBuilder  = new TableRelationshipGraphBuilder();
            var dataJoinTable = _dataSourceComponents.StatsQueryBuilder.GetDataJoinTable(request.GroupByColumn, statsRelationships, graphBuilder);

            // get the stats relationship to the data join table
            var statsRelationship = statsRelationships.FirstOrDefault(x => x.Table1.KnownTableName == dataJoinTable || x.Table2.KnownTableName == dataJoinTable);

            var statForeignKeyToDataTable = statsRelationship.Table1.KnownTableName == dataJoinTable
                       ? statsRelationship.Table2Column
                       : statsRelationship.Table1Column;

            var groupByColumn = _columnProvider.Find(_constants.DataSourceId, _statsTableName, statForeignKeyToDataTable, null).First();

            return(groupByColumn);
        }
        public override void BuildFrom(SelectQuery query, List <ReportColumnMapping> selectedColumns, ReportColumnMapping groupByColumn, ReportColumnMapping sortByColumn, MappedSearchRequest request)
        {
            var statsRelationships = _tableMappings.GetAllTableRelationships()
                                     .Where(x => x.Table1 is StatsTableMapping || x.Table2 is StatsTableMapping)
                                     .ToList();

            // get the data table which joins onto the stats table
            var graphBuilder  = new TableRelationshipGraphBuilder();
            var dataJoinTable = _dataSourceComponents.StatsQueryBuilder.GetDataJoinTable(request.GroupByColumn, statsRelationships, graphBuilder);

            //-- Find out which stats table or view we need to query to satisfy the requested temporal
            // aggregation and type of date range.
            var statsTableName = GetStatsTableName(
                _transposeStatsTableName,
                dataJoinTable,
                request.TemporalAggregation,
                request.DateRangeType,
                request.DateStart,
                request.DateEnd);

            query.From(statsTableName, _transposeStatsTableAlias);
        }
        protected void AddMissingDataTables(
            SelectQuery query,
            ReportColumnMapping groupByColumn,
            TableRelationshipGraphBuilder graphBuilder,
            List <string> tables,
            QueryBuilderBase queryBuilderBase,
            Dictionary <string, bool> addedTables)
        {
            // build a graph of the table relationships to calculate the distance from the root table
            // include missing tables needed for joins
            // order the tables by distance
            var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _constants.RootTableName);

            graphBuilder.TrimToTables(relationshipGraph, tables);
            tables = graphBuilder.GetAllTables(relationshipGraph).Union(tables).Distinct().ToList();

            tables = tables.OrderBy(x => graphBuilder.GetDistance(relationshipGraph, x)).ToList();

            foreach (var table in tables.Distinct())
            {
                queryBuilderBase.AddFromTableJoin(query, groupByColumn, table, ref addedTables, graphBuilder, relationshipGraph);
            }
        }
        public void AddDataTableJoinsUpToRoot(
            SelectQuery query,
            string dataTable,
            TableRelationshipGraphBuilder graphBuilder,
            Dictionary <string, bool> addedTables)
        {
            if (dataTable != _constants.RootTableName)
            {
                var fromTable         = _tableMappings.GetTableMapping(dataTable);
                var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _constants.RootTableName);

                var    path             = graphBuilder.GetPathFromTableToRoot(relationshipGraph, dataTable);
                string currentTableName = fromTable.KnownTableName;
                foreach (var table in path.Skip(1))
                {
                    if (!addedTables.ContainsKey(table))
                    {
                        JoinTables(query, table, currentTableName);
                        addedTables.Add(table, false);
                        currentTableName = table;
                    }
                }
            }
        }
Exemple #9
0
        public virtual void AddFromTableJoin(
            SelectQuery query,
            ReportColumnMapping groupByColumn,
            string tableName,
            ref Dictionary <string, bool> addedTables,
            TableRelationshipGraphBuilder graphBuilder,
            TableRelationshipGraph relationshipGraph)
        {
            var joinTable = _tableMappings.GetTableMapping(tableName);

            if (joinTable.TableType == TableType.Stats)
            {
                return;
            }

            bool isAggregated = false;

            // tables with no child relationships
            if (!addedTables.ContainsKey(tableName))
            {
                var distanceToRootTable = graphBuilder.GetDistance(relationshipGraph, tableName);

                var parentJoin = graphBuilder
                                 .GetByDistance(relationshipGraph, distanceToRootTable - 1) // the level above
                                 .SingleOrDefault(x => x.Relations.Any(y => y.TableName == tableName));

                if (parentJoin != null)
                {
                    var relation = parentJoin.Relations.First(x => x.TableName == tableName);

                    if (relation.Type == TableRelationshipGraphType.Sibling)
                    {
                        //var parentTable = _tableMappings.GetTableMapping(parentJoin.TableName);

                        var aggregatedTables           = addedTables.Where(x => x.Value);
                        var isSiblingOfAggregatedTable = aggregatedTables.Any(x => x.Value && TableIsSiblingOfTable(tableName, x.Key));

                        if (isSiblingOfAggregatedTable)
                        {
                            var parentTable = _tableMappings.GetTableMapping(groupByColumn.KnownTable);

                            // if grouping by the parent of this table, then join on the primary key
                            var joinForeignColumn = parentTable.PrimaryKey;

                            query.LeftJoin(joinTable.CteAlias, joinTable.Alias, _constants.GroupKeyAlias, parentTable.Alias, joinForeignColumn);

                            isAggregated = true;
                        }
                        else
                        {
                            JoinTables(query, tableName, parentJoin.TableName);
                        }
                        addedTables.Add(tableName, isAggregated);
                    }
                    else
                    {
                        var parentTable = _tableMappings.GetTableMapping(parentJoin.TableName);

                        var isChild = TableIsChildOfTable(groupByColumn.KnownTable, joinTable.KnownTableName);
                        var aggregatedViewRequired = !ColumnIsTableOrForeignKeyToTable(groupByColumn, joinTable) && !isChild;

                        if (aggregatedViewRequired)
                        {
                            parentTable = _tableMappings.GetTableMapping(groupByColumn.KnownTable);

                            // if the table being joined cant be connected to the group by table, the CTE will have been grouped by the root table id.
                            if (!graphBuilder.TablesAreInSamePathToRoot(relationshipGraph, tableName, groupByColumn.KnownTable))
                            {
                                parentTable = _tableMappings.GetTableMapping(_constants.RootTableName);
                            }

                            // if grouping by the parent of this table, then join on the primary key
                            var joinForeignColumn = TableIsParentOfTable(groupByColumn.KnownTable, joinTable.KnownTableName) || parentTable.KnownTableName == _constants.RootTableName
                                ? parentTable.PrimaryKey
                                : _constants.GroupKeyAlias;

                            if (addedTables.ContainsKey(parentTable.KnownTableName) && addedTables[parentTable.KnownTableName] == false)
                            {
                                joinForeignColumn = parentTable.PrimaryKey;
                            }

                            query.LeftJoin(joinTable.CteAlias, joinTable.Alias, _constants.GroupKeyAlias, parentTable.Alias, joinForeignColumn);

                            isAggregated = true;
                        }
                        else
                        {
                            JoinTables(query, tableName, parentTable.KnownTableName);
                        }
                        addedTables.Add(tableName, isAggregated);
                    }
                }
                else
                {
                    throw new Exception(string.Format("Could not join table '{0}', no suitable relationship was found", tableName));
                }
            }
        }
Exemple #10
0
        protected override void BuildGroupBy(SelectQuery query, ReportColumnMapping groupByColumn, MappedSearchRequest request)
        {
            _rootTableName = request.GroupByColumn.KnownTable;

            if (_rootTableName == _fromTableName)
            {
                var table = _tableMappings.GetTableMapping(_fromTableName);
                query.GroupBy(table.Alias, table.PrimaryKey);
                return;
            }

            var joinFromTable = _fromTableName;

            var graphBuilder = new TableRelationshipGraphBuilder();

            if (!CanJoinTables(_fromTableName, _rootTableName))
            {
                // if the table cannot be directly joined to the group by table, work out which join table to group on

                var fromTable = _tableMappings.GetTableMapping(_fromTableName);

                var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _rootTableName);

                var distance = graphBuilder.GetDistance(relationshipGraph, _fromTableName);

                joinFromTable = fromTable.KnownTableName;
                while (distance > 1)
                {
                    var potentialNodes = graphBuilder.GetByDistance(relationshipGraph, distance - 1);
                    var parentNode     = potentialNodes.Single(x => x.Relations.Any(y => y.TableName == joinFromTable));
                    joinFromTable = parentNode.TableName;
                    distance--;
                    if (CanJoinTables(_fromTableName, joinFromTable) && CanJoinTables(joinFromTable, _rootTableName))
                    {
                        break;
                    }
                }
            }

            if (CanJoinTables(joinFromTable, _rootTableName))
            {
                var relationship = GetTableRelationships(joinFromTable, _rootTableName).Single();
                if (relationship.Table1.KnownTableName == joinFromTable)
                {
                    query.GroupBy(relationship.Table1.Alias, relationship.Table1Column);
                }
                else if (relationship.Table2.KnownTableName == joinFromTable)
                {
                    query.GroupBy(relationship.Table2.Alias, relationship.Table2Column);
                }
                else
                {
                    throw new Exception("Failed to select group column");
                }
            }

            else
            {
                throw new Exception(string.Format("Cannot join tables {0} to {1}", joinFromTable, _rootTableName));
            }
        }
        public virtual string GetDataJoinTable(ReportColumnMapping groupByColumn, List <TableRelationship> statsRelationships, TableRelationshipGraphBuilder graphBuilder)
        {
            var statsJoinTables = statsRelationships
                                  .Select(x => x.Table1 is StatsTableMapping ? x.Table2.KnownTableName : x.Table1.KnownTableName)
                                  .ToList();

            // find the nearest stats table to the group by table.
            var graph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), groupByColumn.KnownTable);

            graphBuilder.TrimToTables(graph, statsJoinTables);
            var dataTables = graphBuilder.GetAllTables(graph).Distinct().ToList();

            dataTables = dataTables.OrderBy(x => graphBuilder.GetDistance(graph, x)).ToList();

            var joinTable = dataTables.FirstOrDefault(statsJoinTables.Contains);

            return(joinTable);
        }
//        public override Column GetColumnSelector(ReportColumnMapping col, MappedSearchRequest request, bool dontAggregate = false, bool useFieldAlias = false)
//        {

//            var result = base.GetColumnSelector(col, request, dontAggregate: dontAggregate, useFieldAlias: useFieldAlias);

        // to allow selecting both min and max together (not working with custom columns - its complicated)
        // depends on DefaultStatsQueryBuilder.GetColumnSelector()
//           if (IsDateQuery(request) && (result.TableAlias??"").ToLower() == "stats" && !dontAggregate && result.Field.Name != _constants.CountKeyAlias)
//            {
//                result.Field.Name += "_" + col.FieldAggregationMethod;
//            }
//            return result;
//        }

        public override void BuildFrom(SelectQuery query, List <ReportColumnMapping> selectedColumns, ReportColumnMapping groupByColumn, ReportColumnMapping sortByColumn, MappedSearchRequest request)
        {
            using (new DebugTimer("StatsQueryBuilder.BuildFrom"))
            {
                var graphBuilder = new TableRelationshipGraphBuilder();

                var tables = request.SelectedAndDependantColumns.Select(x => x.KnownTable).Distinct().ToList();

                tables.Add(groupByColumn.KnownTable);
                tables = tables.Distinct().ToList();

                var statsRelationships = _tableMappings.GetAllTableRelationships()
                                         .Where(x => x.Table1 is StatsTableMapping || x.Table2 is StatsTableMapping)
                                         .ToList();

                // get the data table which joins onto the stats table
                var dataJoinTable = GetDataJoinTable(groupByColumn, statsRelationships, graphBuilder);

                // get the stats relationship to the data join table
                var statsRelationship = statsRelationships.FirstOrDefault(x => x.Table1.KnownTableName == dataJoinTable || x.Table2.KnownTableName == dataJoinTable);

                string joinCol;
                if (statsRelationship != null)
                {
                    // var dataTable = statsRelationship.Table1.KnownTableName == groupByColumn.KnownTable//
                    var dataTable = statsRelationship.Table1.TableType == TableType.Data
                        ? statsRelationship.Table1.KnownTableName
                        : statsRelationship.Table2.KnownTableName;

                    //var statForeignKeyToDataTable = statsRelationship.Table1.KnownTableName == groupByColumn.KnownTable
                    var statForeignKeyToDataTable = statsRelationship.Table1.TableType == TableType.Data
                        ? statsRelationship.Table2Column
                        : statsRelationship.Table1Column;

                    query.From(GetStatsTableName(dataTable, request), _statsTableAlias);
                    JoinTables(query, dataTable, _statsTableName);
                    joinCol = statForeignKeyToDataTable;


                    var addedTables = new Dictionary <string, bool> {
                        { dataTable, false }
                    };

                    // join back up to the root table  todo : exclude tables not used for filtering or calculations
                    AddDataTableJoinsUpToRoot(query, dataTable, graphBuilder, addedTables);


                    // add data table joins : todo : exclude tables not used for filtering or calculations
                    AddMissingDataTables(query, groupByColumn, graphBuilder, tables, _dataSourceComponents.QueryBuilderBase, addedTables);

                    var currencyColumn = GetCurrencyColumn();
                    if (currencyColumn != null && !addedTables.ContainsKey(currencyColumn.KnownTable))
                    {
                        var relationshipGraph = graphBuilder.Build(_tableMappings.GetAllTableRelationships(), _constants.RootTableName);
                        AddFromTableJoin(query, groupByColumn, currencyColumn.KnownTable, ref addedTables, graphBuilder, relationshipGraph);
                    }
                }
                else
                {
                    throw new Exception("No Relationship found to join the Stats table to " + groupByColumn.KnownTable);
                }

                var resolution = RestrictResolution(request);
                var allTransposeStatsColumns = GetAllTransposeStatsColumns(request);
                var distinctTransposeKeys    = allTransposeStatsColumns.Select(x => QueryHelpers.GetTransposeKeyValue(x)).Distinct();

                AddTransposeStatsJoins(query, resolution, distinctTransposeKeys, joinCol);
            }
        }