Adds the having clauses.

@param havingExpression
the having expression
@param aggregationBuilder
the aggregation builder
@param entityMetadata
the entity metadata
@return the aggregation builder
431238
private AggregationBuilder addHavingClause(Expression havingExpression, AggregationBuilder aggregationBuilder,
            EntityMetadata entityMetadata)
    {
        if (havingExpression instanceof ComparisonExpression)
        {
            Expression expression = ((ComparisonExpression) havingExpression).getLeftExpression();
            if (!isAggregationExpression(expression))
            {
                logger.error("Having clause conditions over non metric aggregated are not supported.");
                throw new UnsupportedOperationException(
                        "Currently, Having clause without Metric aggregations are not supported.");
            }

            return checkIfKeyExists(expression.toParsedText()) ? aggregationBuilder
                    .subAggregation(getMetricsAggregation(expression, entityMetadata)) : aggregationBuilder;
        }
        else if (havingExpression instanceof AndExpression)
        {
            AndExpression andExpression = (AndExpression) havingExpression;
            addHavingClause(andExpression.getLeftExpression(), aggregationBuilder, entityMetadata);
            addHavingClause(andExpression.getRightExpression(), aggregationBuilder, entityMetadata);

            return aggregationBuilder;
        }
        else if (havingExpression instanceof OrExpression)
        {
            OrExpression orExpression = (OrExpression) havingExpression;
            addHavingClause(orExpression.getLeftExpression(), aggregationBuilder, entityMetadata);
            addHavingClause(orExpression.getRightExpression(), aggregationBuilder, entityMetadata);

            return aggregationBuilder;
        }
        else
        {
            logger.error(havingExpression + "not supported in having clause.");
            throw new UnsupportedOperationException(havingExpression + "not supported in having clause.");
        }
    }
57303
func havingExpressionBuilder() ClauseHook {
	var f ClauseHook
	f = func(s *Statement, _ Symbol) (ClauseHook, error) {
		s.havingExpressionEvaluator = &AlwaysReturn{V: true}
		if len(s.havingExpression) > 0 {
			eval, err := NewEvaluator(s.havingExpression)
			if err != nil {
				return nil, err
			}
			s.havingExpressionEvaluator = eval
		}
		return f, nil
	}
	return f
}
1018330
private QueryBuilder populateLikeQuery(LikeExpression likeExpression, EntityMetadata metadata)
    {
        Expression patternValue = likeExpression.getPatternValue();
        String field = likeExpression.getStringExpression().toString();

        String likePattern = (patternValue instanceof InputParameter) ? kunderaQuery.getParametersMap()
                .get((patternValue).toParsedText()).toString() : patternValue.toParsedText().toString();
        String jpaField = getField(field);

        log.debug("Pattern value for field " + field + " is: " + patternValue);
        QueryBuilder filterBuilder = getQueryBuilder(kunderaQuery.new FilterClause(jpaField, Expression.LIKE,
                likePattern, field), metadata);

        return filterBuilder;
    }
1297318
public QueryBuilder populateFilterBuilder(Expression condtionalExp, EntityMetadata m)
    {
        log.info("Populating filter for expression: " + condtionalExp);
        QueryBuilder filter = null;

        if (condtionalExp instanceof SubExpression)
        {
            filter = populateFilterBuilder(((SubExpression) condtionalExp).getExpression(), m);
        }
        else if (condtionalExp instanceof ComparisonExpression)
        {
            filter = getFilter(populateFilterClause((ComparisonExpression) condtionalExp), m);
        }
        else if (condtionalExp instanceof BetweenExpression)
        {
            filter = populateBetweenFilter((BetweenExpression) condtionalExp, m);
        }
        else if (condtionalExp instanceof LogicalExpression)
        {
            filter = populateLogicalFilterBuilder(condtionalExp, m);
        }
        else if (condtionalExp instanceof LikeExpression)
        {
            filter = populateLikeQuery((LikeExpression) condtionalExp, m);
        }
        else if (condtionalExp instanceof InExpression)
        {
            filter = populateInQuery((InExpression) condtionalExp, m);
        }
        else
        {
            log.error(condtionalExp.toParsedText() + "found in where clause. Not supported in elasticsearch.");
            throw new KunderaException(condtionalExp.toParsedText() + " not supported in ElasticSearch");
        }

        log.debug("Following is the populated filter for required query: " + filter);
        return filter;
    }
691499
public static Map<String, Object> setFieldClazzAndColumnFamily(Expression expression, EntityMetadata m,
            final KunderaMetadata kunderaMetadata)
    {
        AbstractPathExpression pathExp = null;

        if (expression instanceof AbstractPathExpression) {
            pathExp = (AbstractPathExpression) expression;

        } else {
            if (expression instanceof AbstractSingleEncapsulatedExpression) {
                pathExp = (AbstractPathExpression) ((AbstractSingleEncapsulatedExpression) expression).getExpression();
            }

        }

        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
                m.getPersistenceUnit());

        EntityType entity = metaModel.entity(m.getEntityClazz());
        String discriminatorColumn = ((AbstractManagedType) entity).getDiscriminatorColumn();
        Class fieldClazz = String.class;
        String colFamily = m.getTableName();
        String colName = null;
        Map<String, Object> map = new HashMap<String, Object>();

        boolean isEmbeddable = false;
        boolean isAssociation = false;
        int count = 1;
        String fieldName = pathExp.getPath(count++);

        AbstractAttribute attrib = (AbstractAttribute) entity.getAttribute(fieldName);
        String dbColName = attrib.getJPAColumnName();
        isEmbeddable = metaModel.isEmbeddable(attrib.getBindableJavaType());
        isAssociation = attrib.isAssociation();
        while (pathExp.pathSize() > count)
        {
            if (isEmbeddable)
            {
                EmbeddableType embeddableType = metaModel.embeddable(attrib.getBindableJavaType());
                String attName = pathExp.getPath(count++);
                fieldName = fieldName + "." + attName;
                attrib = (AbstractAttribute) embeddableType.getAttribute(attName);
                isEmbeddable = metaModel.isEmbeddable(attrib.getBindableJavaType());
                isAssociation = attrib.isAssociation();
                dbColName += ("." + attrib.getJPAColumnName());
            }
            else if (isAssociation)
            {
                String attName = pathExp.getPath(count++);
                fieldName = fieldName + "." + attName;
                EntityType associatedType = metaModel.entity(attrib.getBindableJavaType());
                attrib = (AbstractAttribute) associatedType.getAttribute(attName);
                isEmbeddable = metaModel.isEmbeddable(attrib.getBindableJavaType());
                isAssociation = attrib.isAssociation();
                dbColName += ("." + attrib.getJPAColumnName());
            }
            colName = fieldName;
        }

        if (!pathExp.getPath(count - 1).equals(discriminatorColumn))
        {
            fieldClazz = attrib.getBindableJavaType();
            colFamily = attrib.getTableName() != null ? attrib.getTableName() : m.getTableName();
            colName = colName != null ? colName : attrib.getJPAColumnName();

        }

        boolean ignoreCase =
              (expression instanceof UpperExpression) || (expression instanceof LowerExpression);

        map.put(Constants.FIELD_CLAZZ, fieldClazz);
        map.put(Constants.COL_FAMILY, colFamily);
        map.put(Constants.COL_NAME, colName);
        map.put(Constants.FIELD_NAME, fieldName);
        map.put(Constants.IS_EMBEDDABLE, isEmbeddable);
        map.put(Constants.DB_COL_NAME, dbColName);
        map.put(Constants.IGNORE_CASE, ignoreCase);
        return map;
    }
902312
public static Aggregation translateAggregateCall(
      final PlannerContext plannerContext,
      final DruidQuerySignature querySignature,
      final RexBuilder rexBuilder,
      final Project project,
      final List<Aggregation> existingAggregations,
      final String name,
      final AggregateCall call,
      final boolean finalizeAggregations
  )
  {
    final DimFilter filter;

    if (call.filterArg >= 0) {
      // AGG(xxx) FILTER(WHERE yyy)
      if (project == null) {
        // We need some kind of projection to support filtered aggregations.
        return null;
      }

      final RexNode expression = project.getChildExps().get(call.filterArg);
      final DimFilter nonOptimizedFilter = Expressions.toFilter(plannerContext, querySignature, expression);
      if (nonOptimizedFilter == null) {
        return null;
      } else {
        filter = Filtration.create(nonOptimizedFilter).optimizeFilterOnly(querySignature).getDimFilter();
      }
    } else {
      filter = null;
    }

    final SqlAggregator sqlAggregator = plannerContext.getOperatorTable()
                                                      .lookupAggregator(call.getAggregation());

    if (sqlAggregator == null) {
      return null;
    }

    // Compute existingAggregations for SqlAggregator impls that want it.
    final List<Aggregation> existingAggregationsWithSameFilter = new ArrayList<>();
    for (Aggregation existingAggregation : existingAggregations) {
      if (filter == null) {
        final boolean doesMatch = existingAggregation.getAggregatorFactories().stream().noneMatch(
            factory -> factory instanceof FilteredAggregatorFactory
        );

        if (doesMatch) {
          existingAggregationsWithSameFilter.add(existingAggregation);
        }
      } else {
        final boolean doesMatch = existingAggregation.getAggregatorFactories().stream().allMatch(
            factory -> factory instanceof FilteredAggregatorFactory &&
                       ((FilteredAggregatorFactory) factory).getFilter().equals(filter)
        );

        if (doesMatch) {
          existingAggregationsWithSameFilter.add(
              Aggregation.create(
                  existingAggregation.getVirtualColumns(),
                  existingAggregation.getAggregatorFactories().stream()
                                     .map(factory -> ((FilteredAggregatorFactory) factory).getAggregator())
                                     .collect(Collectors.toList()),
                  existingAggregation.getPostAggregator()
              )
          );
        }
      }
    }

    final Aggregation retVal = sqlAggregator.toDruidAggregation(
        plannerContext,
        querySignature,
        rexBuilder,
        name, call, project, existingAggregationsWithSameFilter,
        finalizeAggregations
    );

    if (retVal == null) {
      return null;
    } else {
      // Check if this refers to the existingAggregationsWithSameFilter. If so, no need to apply the filter.
      if (isUsingExistingAggregation(retVal, existingAggregationsWithSameFilter)) {
        return retVal;
      } else {
        return retVal.filter(querySignature, filter);
      }
    }
  }
922938
public function addHaving(array $having): void
    {
        if (empty($having)) {
            return;
        }

        $firstClause = true;
        $this->statement .= ' HAVING ';
        foreach ($having as $clause) {
            if ($firstClause === false) {
                $this->statement .= ' ' . $clause['concatenator'] . ' ';
            }
            $placeholder = $this->addBindingValue($clause['key'], $clause['value']);
            $key = $this->quoteName($clause['key']);
            $this->statement .= sprintf('%s %s %s', $key, $clause['operator'], $placeholder);
            $this->statement .= PHP_EOL;
            $firstClause = false;
        }
    }
1254919
private function addMatch(Builder $aggregationBuilder, string $field, string $operator, string $value, string $nullManagement = null): void
    {
        try {
            $value = new \DateTime($value);
        } catch (\Exception $e) {
            // Silently ignore this filter if it can not be transformed to a \DateTime
            $this->logger->notice('Invalid filter ignored', [
                'exception' => new InvalidArgumentException(sprintf('The field "%s" has a wrong date format. Use one accepted by the \DateTime constructor', $field)),
            ]);

            return;
        }

        $operatorValue = [
            self::PARAMETER_BEFORE => '$lte',
            self::PARAMETER_STRICTLY_BEFORE => '$lt',
            self::PARAMETER_AFTER => '$gte',
            self::PARAMETER_STRICTLY_AFTER => '$gt',
        ];

        if ((self::INCLUDE_NULL_BEFORE === $nullManagement && \in_array($operator, [self::PARAMETER_BEFORE, self::PARAMETER_STRICTLY_BEFORE], true)) ||
            (self::INCLUDE_NULL_AFTER === $nullManagement && \in_array($operator, [self::PARAMETER_AFTER, self::PARAMETER_STRICTLY_AFTER], true)) ||
            (self::INCLUDE_NULL_BEFORE_AND_AFTER === $nullManagement && \in_array($operator, [self::PARAMETER_AFTER, self::PARAMETER_STRICTLY_AFTER, self::PARAMETER_BEFORE, self::PARAMETER_STRICTLY_BEFORE], true))
        ) {
            $aggregationBuilder->match()->addOr(
                $aggregationBuilder->matchExpr()->field($field)->operator($operatorValue[$operator], $value),
                $aggregationBuilder->matchExpr()->field($field)->equals(null)
            );

            return;
        }

        $aggregationBuilder->match()->addAnd($aggregationBuilder->matchExpr()->field($field)->operator($operatorValue[$operator], $value));
    }
438312
private MetricsAggregationBuilder getMetricsAggregation(Expression expression, EntityMetadata entityMetadata)
    {
        AggregateFunction function = (AggregateFunction) expression;
        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
                entityMetadata.getPersistenceUnit());
        String jPAColumnName = KunderaCoreUtils.getJPAColumnName(function.toParsedText(), entityMetadata, metaModel);

        MetricsAggregationBuilder aggregationBuilder = null;

        switch (function.getIdentifier())
        {
        case Expression.MIN:
            aggregationBuilder = AggregationBuilders.min(function.toParsedText()).field(jPAColumnName);
            break;
        case Expression.MAX:
            aggregationBuilder = AggregationBuilders.max(function.toParsedText()).field(jPAColumnName);
            break;
        case Expression.SUM:
            aggregationBuilder = AggregationBuilders.sum(function.toParsedText()).field(jPAColumnName);
            break;
        case Expression.AVG:
            aggregationBuilder = AggregationBuilders.avg(function.toParsedText()).field(jPAColumnName);
            break;
        case Expression.COUNT:
            aggregationBuilder = AggregationBuilders.count(function.toParsedText()).field(jPAColumnName);
            break;
        }
        return aggregationBuilder;
    }
131776
@NonNull
    @Override
    public GroupBy groupBy(@NonNull Expression... expressions) {
        if (expressions == null) {
            throw new IllegalArgumentException("expressions cannot be null.");
        }
        return new GroupBy(this, Arrays.asList(expressions));
    }
521366
public function having($column, $operator = '=', $value = null)
    {
        $this->havingType = 'AND';

        return $this->addCondition('having', $column, $operator, $value);
    }
129240
private QueryBuilder getFilter(FilterClause clause, final EntityMetadata metadata)
    {
        String condition = clause.getCondition();
        Object value = condition.equals(Expression.IN) ? clause.getValue() : clause.getValue().get(0);
        String name = ((AbstractAttribute) ((MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
                metadata.getPersistenceUnit())).entity(metadata.getEntityClazz()).getAttribute(clause.getProperty()))
                .getJPAColumnName();

        QueryBuilder filterBuilder = null;

        if (condition.equals(Expression.EQUAL))
        {
            filterBuilder = new TermQueryBuilder(name, value);
        }
        else if (condition.equals(Expression.GREATER_THAN))
        {
            filterBuilder = new RangeQueryBuilder(name).gt(value);
        }
        else if (condition.equals(Expression.LOWER_THAN))
        {
            filterBuilder = new RangeQueryBuilder(name).lt(value);
        }
        else if (condition.equals(Expression.GREATER_THAN_OR_EQUAL))
        {
            filterBuilder = new RangeQueryBuilder(name).gte(value);
        }
        else if (condition.equals(Expression.LOWER_THAN_OR_EQUAL))
        {
            filterBuilder = new RangeQueryBuilder(name).lte(value);
        }
        else if (condition.equals(Expression.DIFFERENT))
        {
            filterBuilder = new NotQueryBuilder(new TermQueryBuilder(name, value));
        }
        else if (condition.equals(Expression.IN))
        {
            filterBuilder = new TermsQueryBuilder(name, clause.getValue());
        }

        return filterBuilder;
    }
582449
private static String initCreateRelationshipQuery(EntityKeyMetadata ownerEntityKeyMetadata, AssociationKeyMetadata associationKeyMetadata) {
		EntityKeyMetadata targetEntityKeyMetadata = associationKeyMetadata.getAssociatedEntityKeyMetadata().getEntityKeyMetadata();
		int offset = 0;
		StringBuilder queryBuilder = new StringBuilder( "MATCH " );
		appendEntityNode( "n", ownerEntityKeyMetadata, queryBuilder );
		queryBuilder.append( ", " );
		offset += ownerEntityKeyMetadata.getColumnNames().length;
		appendEntityNode( "t", targetEntityKeyMetadata, queryBuilder, offset );
		queryBuilder.append( " MERGE (n)" );
		queryBuilder.append( " -[r" );
		queryBuilder.append( ":" );
		appendRelationshipType( queryBuilder, associationKeyMetadata );
		offset = ownerEntityKeyMetadata.getColumnNames().length;
		if ( associationKeyMetadata.getRowKeyIndexColumnNames().length > 0 ) {
			offset += targetEntityKeyMetadata.getColumnNames().length;
			appendProperties( queryBuilder, associationKeyMetadata.getRowKeyIndexColumnNames(), offset );
		}
		queryBuilder.append( "]-> (t)" );
		queryBuilder.append( " RETURN r" );
		return queryBuilder.toString();
	}
1237653
public static Expression having(String operator, Val<Expression>[] args) {
        if (args.length > 0) {
            return HavingExpression.of(transformArgsToList(operator, args));
        }
        throw new QuerySyntaxException(Messages.get("dsl.arguments.error0", operator));
    }
1172567
private static String initFindRelationshipQuery(EntityKeyMetadata ownerEntityKeyMetadata, AssociationKeyMetadata associationKeyMetadata) {
		int offset = 0;
		StringBuilder queryBuilder = new StringBuilder( "MATCH " );
		queryBuilder.append( "(n:" );
		queryBuilder.append( ENTITY );
		queryBuilder.append( ":" );
		appendLabel( ownerEntityKeyMetadata, queryBuilder );
		appendProperties( ownerEntityKeyMetadata, queryBuilder );
		queryBuilder.append( ") - " );
		queryBuilder.append( "[r" );
		queryBuilder.append( ":" );
		appendRelationshipType( queryBuilder, associationKeyMetadata );
		offset = ownerEntityKeyMetadata.getColumnNames().length;
		if ( associationKeyMetadata.getRowKeyIndexColumnNames().length > 0 ) {
			appendProperties( queryBuilder, associationKeyMetadata.getRowKeyIndexColumnNames(), offset );
			queryBuilder.append( "] - (t" );
		}
		else {
			queryBuilder.append( "] - (t" );
			appendProperties( queryBuilder, associationKeyMetadata.getAssociatedEntityKeyMetadata().getEntityKeyMetadata().getColumnNames(), offset );
		}
		queryBuilder.append( ")" );
		queryBuilder.append( " RETURN r" );
		return queryBuilder.toString();
	}
1186292
private AggregationBuilder appendAggregation(CollectionExpression collectionExpression,
            EntityMetadata entityMetadata, AggregationBuilder aggregationBuilder)
    {
        ListIterable<Expression> functionlist = collectionExpression.children();
        for (Expression function : functionlist)
        {
            if (isAggregationExpression(function) && checkIfKeyExists(function.toParsedText()))
            {
                aggregationBuilder.subAggregation(getMetricsAggregation(function, entityMetadata));
            }
        }
        return aggregationBuilder;
    }
781198
@SuppressWarnings("unchecked")
    public <T> Predicate byPattern(Root<T> root, CriteriaBuilder builder, SearchParameters sp, Class<T> type) {
        if (!sp.hasSearchPattern()) {
            return null;
        }

        List<Predicate> predicates = newArrayList();
        EntityType<T> entity = em.getMetamodel().entity(type);
        String pattern = sp.getSearchPattern();

        for (SingularAttribute<? super T, ?> attr : entity.getSingularAttributes()) {
            if (attr.getPersistentAttributeType() == MANY_TO_ONE || attr.getPersistentAttributeType() == ONE_TO_ONE) {
                continue;
            }

            if (attr.getJavaType() == String.class) {
                predicates.add(jpaUtil.stringPredicate((Expression<String>) root.get(jpaUtil.attribute(entity, attr)), pattern, sp, builder));
            }
        }

        return jpaUtil.orPredicate(builder, predicates);
    }