![JAR search and dependency download from the Maven repository](/logo.png)
it.unibz.inf.ontop.generation.serializer.impl.DremioSelectFromWhereSerializer Maven / Gradle / Ivy
The newest version!
package it.unibz.inf.ontop.generation.serializer.impl;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import it.unibz.inf.ontop.dbschema.DBParameters;
import it.unibz.inf.ontop.dbschema.QualifiedAttributeID;
import it.unibz.inf.ontop.generation.algebra.SQLFlattenExpression;
import it.unibz.inf.ontop.generation.algebra.SelectFromWhereWithModifiers;
import it.unibz.inf.ontop.generation.serializer.SQLSerializationException;
import it.unibz.inf.ontop.generation.serializer.SelectFromWhereSerializer;
import it.unibz.inf.ontop.model.term.*;
import it.unibz.inf.ontop.model.type.DBTermType;
import it.unibz.inf.ontop.utils.ImmutableCollectors;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@Singleton
public class DremioSelectFromWhereSerializer extends DefaultSelectFromWhereSerializer implements SelectFromWhereSerializer {
@Inject
private DremioSelectFromWhereSerializer(TermFactory termFactory) {
super(new DefaultSQLTermSerializer(termFactory) {
@Override
public String serialize(ImmutableTerm term, ImmutableMap columnIDs) {
return super.serialize(term,columnIDs);
}
@Override
protected String serializeDatetimeConstant(String datetime, DBTermType dbType) {
return String.format("CAST(%s AS %s)", serializeStringConstant(datetime), dbType.getCastName());
}
});
}
@Override
public QuerySerialization serialize(SelectFromWhereWithModifiers selectFromWhere, DBParameters dbParameters) {
return selectFromWhere.acceptVisitor(
new DefaultRelationVisitingSerializer(dbParameters.getQuotedIDFactory()) {
@Override
protected String serializeLimitOffset(long limit, long offset, boolean noSortCondition) {
return String.format("LIMIT %d OFFSET %d", limit, offset);
}
//Due to a limitation of dremio, we need to cast integer constants in VALUES terms to integers, as they would be types as int64 otherwise.
@Override
protected String serializeValuesEntry(Constant constant, ImmutableMap childColumnIDs) {
String serialization = sqlTermSerializer.serialize(constant, childColumnIDs);
if(constant instanceof DBConstant && ((DBConstant) constant).getType().getCategory() == DBTermType.Category.INTEGER) {
return String.format("CAST(%s as INTEGER)", serialization);
}
return serialization;
}
// @Override
// protected String serializeProjection(ImmutableSortedSet projectedVariables,
// ImmutableMap variableAliases,
// ImmutableSubstitution extends ImmutableTerm> substitution,
// ImmutableMap columnIDs) {
//
// if (projectedVariables.isEmpty())
// return "1 AS uselessVariable";
//
// return projectedVariables.stream()
// .map(v -> serializeDef(
// v,
// Optional.ofNullable((ImmutableTerm)substitution.get(v)).orElse(v),
// columnIDs,
// variableAliases
// ))
// .collect(Collectors.joining(", "));
// }
// private String serializeDef(Variable v, ImmutableTerm term, ImmutableMap columnIDs, ImmutableMap variableAliases) {
// return serializeValue(term, columnIDs) + " AS " + variableAliases.get(v).getSQLRendering();
// }
//
// private String serializeValue(ImmutableTerm term, ImmutableMap columnIDs) {
// return term.isNull()?
// castNull(term.inferType()):
// sqlTermSerializer.serialize(
// term,
// columnIDs
// );
// }
//
// private String castNull(Optional inferType) {
// return String.format(
// "CAST(NULL AS %s)",
// inferType.orElseThrow(
// () ->new SQLSerializationException("a type is expected")));
// }
@Override
protected QuerySerialization serializeFlatten(SQLFlattenExpression sqlFlattenExpression, Variable flattenedVar, Variable outputVar, Optional indexVar, DBTermType flattenedType, ImmutableMap allColumnIDs, QuerySerialization subQuerySerialization) {
if(indexVar.isPresent()) {
throw new SQLSerializationException("Dremio does not support FLATTEN with position arguments.");
}
//We express the flatten call as a `SELECT *, FLATTEN({array}) FROM child.
//FLATTEN only works on ARRAY types, so we first transform the JSON-array into an ARRAY if it is not already one
var expression = flattenedType.getCategory() == DBTermType.Category.ARRAY
? allColumnIDs.get(flattenedVar).getSQLRendering()
: String.format("CONVERT_FROM(%s, 'json')", allColumnIDs.get(flattenedVar).getSQLRendering());
//We compute an alias for the sub-query, and new aliases for each projected variable.
var alias = this.generateFreshViewAlias().getSQLRendering();
var variableAliases = allColumnIDs.entrySet().stream()
.filter(e -> e.getKey() != flattenedVar)
.collect(ImmutableCollectors.toMap(
v -> v.getKey(),
v -> new QualifiedAttributeID(idFactory.createRelationID(alias), v.getValue().getAttribute())
));
var subProjection = subQuerySerialization.getColumnIDs().keySet().stream()
.filter(v -> variableAliases.containsKey(v))
.map(
v -> subQuerySerialization.getColumnIDs().get(v).getSQLRendering() + " AS " + idFactory.createAttributeID(v.getName()).getSQLRendering()
)
.collect(Collectors.joining(", "));
if(subProjection.length() > 0)
subProjection += ",";
var builder = new StringBuilder();
/*We need to run `CASE WHEN RAND() > 1...` here, because otherwise, casting the resulting column to
* a different datatype will make the query fail.
* We need to add a LIMIT to the end, because otherwise, when accessing a JSON object that is the
* result of flatten with square brackets, the access operation will be ignored.
* */
builder.append(String.format(
"(SELECT %s CASE WHEN RAND() > 1 THEN NULL ELSE FLATTEN(%s) END AS %s FROM %s LIMIT 99999999999999) %s",
subProjection,
expression,
allColumnIDs.get(outputVar).getSQLRendering(),
subQuerySerialization.getString(),
alias
));
return new QuerySerializationImpl(
builder.toString(),
variableAliases
);
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy