/// <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);
        }