/// <summary> /// Removes invalid selections e.g. hidden selections still being sent from the client. /// The client keep them since they can be visible when the filters changes. /// This is only applicable for discrete facets (range facet selection are always visible) /// </summary> /// <param name="facetsConfig"></param> /// <returns></returns> public FacetsConfig2 Update(FacetsConfig2 facetsConfig) { foreach (string facetCode in facetsConfig.GetFacetCodes()) { var config = facetsConfig.GetConfig(facetCode); if (config.Facet.FacetTypeId != EFacetType.Discrete || config.Picks.Count == 0) { continue; } if (!config.HasPicks()) { continue; } config.Picks = QueryProxy.QueryRows( PicksCompiler.Compile( QuerySetupBuilder.Build(facetsConfig, config.Facet, null, null), config.GetIntegerPickValues() ), x => new FacetConfigPick(EPickType.discrete, x.GetString(0), x.GetString(1)) ); } return(facetsConfig); }
/// <summary> /// This the core of the query builder that builds SQL query components for a given target facet, and the /// chain of facet configurations preceeding the target facet. /// Rules: /// - Collect/compile users pick constraint for all involved facets current facet /// - All picks *predeeding* target facet should be included /// - If target is a "discrete" facet then the facet's own constraints should NOT be included. /// - If target facet is "range" then the facet's own constraints should be included, /// but the bound should be expanded to the facet's entire range. /// - Get all selection preceding the target facet. /// - Make where-clauses depending on type of facets (range or discrete) /// </summary> /// <param name="facetsConfig">The (complete) facet configuration, including user picks</param> /// <param name="targetFacet">Target facet that the query populates/computes/counts etc</param> /// <param name="extraTables">,Any extra tables that should be part of the query (path to these tables are included in final query)</param> /// <param name="facetCodes">FIXME: "The list of the facets in the view-state"</param> /// <returns> /// QuerySetup: /// TargetConfig Reference to targets facet's configuration (only added for convenience) /// Facet Reference to target facet (only added for convenience) /// Routes Compiled routes (added for easier testing purposes) /// Joins Join clauses to be used in final SQL /// Criterias Criteria clauses to be included in final SQL /// </returns> public QuerySetup Build(FacetsConfig2 facetsConfig, Facet targetFacet, List <string> extraTables, List <string> facetCodes) { // Noteworthy: TargetFacet differs from facetsConfig.TargetFacet when a result-facet is applied var involvedConfigs = facetsConfig.GetFacetConfigsAffectedBy(targetFacet, facetCodes); if (facetsConfig.HasDomainCode()) { involvedConfigs.Insert(0, facetsConfig.CreateDomainConfig()); } var pickCriterias = PicksCompiler.Compile(targetFacet, involvedConfigs); var involvedFacets = involvedConfigs.Facets().AddUnion(targetFacet).ToList(); var involvedTables = involvedFacets.TableNames().NullableUnion(extraTables).Distinct().ToList(); var involvedJoins = JoinCompiler.Compile(facetsConfig, targetFacet, involvedTables); var facetCriterias = involvedFacets.Criterias(); QuerySetup querySetup = new QuerySetup() { TargetConfig = facetsConfig?.TargetConfig, Facet = targetFacet, Joins = involvedJoins, Criterias = pickCriterias.Concat(facetCriterias).ToList() }; return(querySetup); }