Skip to content

Commit

Permalink
Extracted shared code into StageUtil
Browse files Browse the repository at this point in the history
and restored original Stage ordering.
  • Loading branch information
Jugen committed Feb 12, 2024
1 parent 3c508b6 commit ab94583
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ public class DefaultSelectTranslator implements SelectTranslator {
private static final TranslationStage[] TRANSLATION_STAGES = {
new ColumnExtractorStage(),
new PrefetchNodeStage(),
new OrderingStage(),
new QualifierTranslationStage(),
new HavingTranslationStage(),
new GroupByStage(),
new DistinctStage(),
new OrderingStage(), // DistinctStage is a prerequisite
new GroupByStage(), // OrderingStage is a prerequisite
new LimitOffsetStage(),
new ColumnDescriptorStage(),
new TableTreeQualifierStage(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,15 @@

package org.apache.cayenne.access.translator.select;

import java.sql.Types;

/**
* @since 4.2
*/
class DistinctStage implements TranslationStage {

private static final int[] UNSUPPORTED_DISTINCT_TYPES = {
Types.BLOB,
Types.CLOB,
Types.NCLOB,
Types.LONGVARCHAR,
Types.LONGNVARCHAR,
Types.LONGVARBINARY
};

static boolean isUnsupportedForDistinct(int type) {
for (int unsupportedDistinctType : UNSUPPORTED_DISTINCT_TYPES) {
if (unsupportedDistinctType == type) {
return true;
}
}

return false;
}

@Override
public void perform(TranslatorContext context) {
// explicit suppressing of distinct
if(context.getMetadata().isSuppressingDistinct()) {
context.setDistinctSuppression(true);
return;
}

// query forcing distinct or query have joins (qualifier or prefetch)
if(!context.getQuery().isDistinct() && !context.getTableTree().hasToManyJoin()) {
return;
}

// unsuitable jdbc type for distinct clause
for(ResultNodeDescriptor node : context.getResultNodeList()) {
// TODO: make it per adapter rather than one-for-all
if(isUnsupportedForDistinct(node.getJdbcType())) {
context.setDistinctSuppression(true);
return;
}
if (StageUtil.isDistinct(context)) {
context.getSelectBuilder().distinct();
}
context.getSelectBuilder().distinct();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@

package org.apache.cayenne.access.translator.select;

import org.apache.cayenne.exp.parser.ASTAggregateFunctionCall;
import org.apache.cayenne.query.Ordering;

/**
* @since 4.2
*/
class GroupByStage implements TranslationStage {

@Override
public void perform(TranslatorContext context) {
if (!hasAggregate(context)) {
if (!StageUtil.hasAggregate(context)) {
return;
}

Expand All @@ -40,26 +37,4 @@ public void perform(TranslatorContext context) {
context.getSelectBuilder().groupBy(resultNode.getNode().deepCopy());
}
}

static boolean hasAggregate(TranslatorContext context) {
if(context.getQuery().getHavingQualifier() != null) {
return true;
}

for(ResultNodeDescriptor resultNode : context.getResultNodeList()) {
if(resultNode.isAggregate()) {
return true;
}
}

if(context.getQuery().getOrderings() != null) {
for(Ordering ordering : context.getQuery().getOrderings()) {
if(ordering.getSortSpec() instanceof ASTAggregateFunctionCall) {
return true;
}
}
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.apache.cayenne.access.translator.select;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.cayenne.access.sqlbuilder.NodeBuilder;
import org.apache.cayenne.access.sqlbuilder.OrderingNodeBuilder;
Expand Down Expand Up @@ -48,7 +47,7 @@ public void perform(TranslatorContext context) {
return;
}

isDistinctOrGroupByQuery = GroupByStage.hasAggregate(context) || isDistinct(context);
isDistinctOrGroupByQuery = StageUtil.hasAggregate(context) || StageUtil.isDistinct(context);

QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
for(Ordering ordering : context.getQuery().getOrderings()) {
Expand All @@ -66,7 +65,7 @@ private void processOrdering(QualifierTranslator qualifierTranslator, Translator
}

// If query is DISTINCT or GROUPING then we need to add all missing ORDER BY clauses as result columns
if (isDistinctOrGroupByQuery) {
if (isDistinctOrGroupByQuery || isCompoundPath(ordering)) {
Optional<Node> column = getResultColumn(context, order(nodeBuilder));
if (!column.isPresent()) {
// deepCopy as some DB expect exactly the same expression in select and in ordering
Expand All @@ -84,6 +83,10 @@ private void processOrdering(QualifierTranslator qualifierTranslator, Translator
context.getSelectBuilder().orderBy(orderingNodeBuilder);
}

private boolean isCompoundPath(Ordering ordering) {
return ordering.getSortSpecString().indexOf('.') > 0;
}

private Optional<Node> getResultColumn(TranslatorContext context, OrderingNodeBuilder orderBuilder) {
String orderStr = getSqlString(orderBuilder);

Expand All @@ -105,10 +108,4 @@ private String getSqlString(NodeBuilder nb) {
node.visit(sqlVisitor);
return strBuilder.append(' ').toString();
}

private boolean isDistinct(TranslatorContext context) {
return !context.isDistinctSuppression()
&& (context.getQuery().isDistinct()
|| context.getTableTree().hasToManyJoin());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.apache.cayenne.access.translator.select;

import java.sql.Types;

import org.apache.cayenne.exp.parser.ASTAggregateFunctionCall;
import org.apache.cayenne.query.Ordering;

public class StageUtil
{
private static final int[] UNSUPPORTED_DISTINCT_TYPES = {
Types.BLOB,
Types.CLOB,
Types.NCLOB,
Types.LONGVARCHAR,
Types.LONGNVARCHAR,
Types.LONGVARBINARY
};

private static boolean isUnsupportedForDistinct(int type) {
for (int unsupportedDistinctType : UNSUPPORTED_DISTINCT_TYPES) {
if (unsupportedDistinctType == type) {
return true;
}
}

return false;
}

static boolean isDistinct(TranslatorContext context) {
// explicit suppressing of distinct
if(context.getMetadata().isSuppressingDistinct()) {
context.setDistinctSuppression(true);
return false;
}

// query forcing distinct or query have joins (qualifier or prefetch)
if(!context.getQuery().isDistinct() && !context.getTableTree().hasToManyJoin()) {
return false;
}

// unsuitable jdbc type for distinct clause
for(ResultNodeDescriptor node : context.getResultNodeList()) {
// TODO: make it per adapter rather than one-for-all
if(isUnsupportedForDistinct(node.getJdbcType())) {
context.setDistinctSuppression(true);
return false;
}
}

return true;
}

static boolean hasAggregate(TranslatorContext context) {
if(context.getQuery().getHavingQualifier() != null) {
return true;
}

for(ResultNodeDescriptor resultNode : context.getResultNodeList()) {
if(resultNode.isAggregate()) {
return true;
}
}

if(context.getQuery().getOrderings() != null) {
for(Ordering ordering : context.getQuery().getOrderings()) {
if(ordering.getSortSpec() instanceof ASTAggregateFunctionCall) {
return true;
}
}
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@ public class DistinctStageTest {

@Test
public void isUnsupportedForDistinct() {
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.BLOB));
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.CLOB));
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.NCLOB));
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.LONGVARCHAR));
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.LONGNVARCHAR));
assertTrue(DistinctStage.isUnsupportedForDistinct(Types.LONGVARBINARY));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.INTEGER));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.DATE));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.CHAR));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.DECIMAL));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.FLOAT));
assertFalse(DistinctStage.isUnsupportedForDistinct(Types.VARCHAR));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.BLOB));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.CLOB));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.NCLOB));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.LONGVARCHAR));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.LONGNVARCHAR));
assertTrue(StageUtil.isUnsupportedForDistinct(Types.LONGVARBINARY));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.INTEGER));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.DATE));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.CHAR));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.DECIMAL));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.FLOAT));
assertFalse(StageUtil.isUnsupportedForDistinct(Types.VARCHAR));
}

@Test
Expand Down

0 comments on commit ab94583

Please sign in to comment.