package org.aksw.sparqlify.core.algorithms;
import java.util.ArrayList;
import java.util.List;
import org.aksw.commons.util.reflect.MultiMethod;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOp;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpDistinct;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpEmpty;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpFilter;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpJoin;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpProject;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpQuery;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpRename;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpSelectBlock;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpSlice;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpTable;
import org.aksw.sparqlify.algebra.sql.nodes.SqlOpUnionN;
import org.apache.jena.sdb.core.Generator;
import org.apache.jena.sdb.core.Gensym;
import org.apache.jena.sparql.expr.ExprVar;
/**
* Pitfalls:
* (distinct (project ...)) -> First project then make distinct
* -> Select Distinct [project]
* But
* (project (distinct ...)) -> First make distinct (with potentially some different projection),
* then project:
* Select [projection] FROM (Select Distinct * From ...)
*
*
* @author Claus Stadler <cstadler@informatik.uni-leipzig.de>
*
*/
public class SqlOpSelectBlockCollector {
private static Generator aliasGenerator = Gensym.create("a");
/*
public static boolean isModifier(SqlOp sqlOp) {
}
*/
public static SqlOpSelectBlock _makeSelect(SqlOp sqlOp) {
SqlOpSelectBlock result = MultiMethod.invokeStatic(SqlOpSelectBlockCollector.class, "makeSelect", sqlOp, null);
return result;
}
public static SqlOpSelectBlock _makeSelect(SqlOp sqlOp, SqlOpSelectBlock context) {
SqlOpSelectBlock result = MultiMethod.invokeStatic(SqlOpSelectBlockCollector.class, "makeSelect", sqlOp, null);
return result;
}
/*
public static SqlOpSelectBlock makeSelect(SqlGroup node) {
SqlOpSelectBlock result;
if(node.getSubOp() instanceof SqlOpSlice) {
SqlOpSelectBlock tmp = _makeSelect(node.getSubOp());
result = new SqlOpSelectBlock(tmp.getAliasName(), tmp);
copyProjection(result, result);
}
else {
result = _makeSelect(node.getSubOp());
}
System.err.println("TODO Handle group by vars if present");
return result;
}
*/
public static SqlOpSelectBlock makeSelect(SqlOpTable node) {
SqlOpTable opTable = makeSelectOrTable(node);
SqlOpSelectBlock result = SqlOpSelectBlock.create(opTable);
for(String columnName : opTable.getSchema().getColumnNames()) {
result.getProjection().put(columnName, new ExprVar(opTable.getAliasName() + "." + columnName));
}
return result;
}
public static SqlOpSelectBlock makeSelect(SqlOpQuery node) {
SqlOpQuery opQuery = makeSelectOrTable(node);
SqlOpSelectBlock result = SqlOpSelectBlock.create(opQuery);
for(String columnName : opQuery.getSchema().getColumnNames()) {
result.getProjection().put(columnName, new ExprVar(opQuery.getAliasName() + "." + columnName));
}
return result;
}
public static SqlOpSelectBlock requireContext(SqlOp node, SqlOpSelectBlock context) {
if(context != null) {
return context;
}
SqlOpSelectBlock result = SqlOpSelectBlock.create(node);
return result;
}
public static SqlOpSelectBlock makeSelect(SqlOpFilter op) {
SqlOp effectiveOp = _makeSelect(op.getSubOp());
// SqlOpSelectBlock result = null; requireSelectBlock(effectiveOp, op);
result.getConditions().addAll(op.getExprs());
return result;
}
public static SqlOpSelectBlock makeSelect(SqlOpSlice node) {
SqlOpSelectBlock result = _makeSelect(node.getSubOp());
SqlOpSelectBlock.slice(null, result, node.getOffset(), node.getLimit());
return result;
}
public static SqlOpSelectBlock makeSelect(SqlOpDistinct node) {
SqlOpSelectBlock result = _makeSelect(node.getSubOp());
result.setDistinct(true);
return result;
}
/*
public static SqlOpSelectBlock makeSelect(SqlAlias node) {
if(true) {
SqlOpSelectBlock result = _makeSelect(node.getSubOp());
//result.setAliasName(node.getAliasName());
SqlOpSelectBlock wrap = new SqlOpSelectBlock(node.getAliasName(), result);
copyProjection(wrap, result);
return wrap;
/*
copyProjection(result, node);
result.setAliasName(node.getAliasName());
return result;
* /
}
//throw new RuntimeException("Should not come here");
SqlOp result = _makeSelectOrTable(node.getSubOp());
SqlOpSelectBlock wrap = new SqlOpSelectBlock(node.getAliasName(), result);
copyProjection(wrap, result);
return wrap;
/*
wrap.getSparqlVarToExprs().putAll(node.getSparqlVarToExprs());
wrap.getAliasToColumn().putAll(node.getAliasToColumn());
result.setAliasName(node.getAliasName());
return result;
* /
}
*/
/*
public static SqlOpSelectBlock makeSelect(SqlOpOrder node) {
SqlOpSelectBlock result = _makeSelect(node.getSubOp());
result.getSortConditions().addAll(node.getConditions());
copyProjection(result, node);
return result;
}
*/
public static SqlOpSelectBlock makeSelect(SqlOpProject node) {
SqlOpSelectBlock result = _makeSelect(node.getSubOp());
// If the node is distinct, or if it already has a projection set,
// we must create a subselect
if(result.isDistinct()) { // || result.isResultStar()
//SqlOpSelectBlock wrapped = new
}
return result;
}
// public static priority
public static SqlOpSelectBlock makeSelect(SqlOpRename op) {
SqlOp tmp = _makeSelectOrTable(op.getSubOp());
SqlOpSelectBlock result = requireSelectBlock(tmp, op);
result.getProjection().renameAll(op.getRename());
return result;
}
public static SqlOpSelectBlock makeSelect(SqlOpJoin node, SqlOpSelectBlock context) {
SqlOpSelectBlock result = requireContext(node, context);
//SqlOp join = makeSelectOrTable(node, result);
return new SqlOpSelectBlock(null);
}
public static SqlOpSelectBlock makeSelect(SqlOpUnionN node) {
// Wrap all elements of the union
List<SqlOp> wrapped = new ArrayList<SqlOp>();
for(SqlOp arg : node.getSubOps()) {
SqlOpSelectBlock argSelect = _makeSelect(arg);
/*
argSelect.getSparqlVarToExprs().clear();
argSelect.getAliasToColumn().clear();
argSelect.getSparqlVarToExprs().putAll(arg.getSparqlVarToExprs());
argSelect.getAliasToColumn().putAll(arg.getAliasToColumn());
*/
wrapped.add(argSelect);
}
SqlOpUnionN union = SqlOpUnionN.create(wrapped); //, SqlOpSelectBlock.getAliasName(node));
SqlOpSelectBlock result = SqlOpSelectBlock.create(union);
return result;
}
public static SqlOp _makeSelectOrTable(SqlOp node) {
return MultiMethod.invokeStatic(SqlOpSelectBlockCollector.class, "makeSelectOrTable", node);
}
public static SqlOp makeSelectOrTable(SqlOpEmpty node) {
throw new RuntimeException("Empty SQL node");
// Should never come here
return node;
}
public static SqlOp makeSelectOrTable(SqlOpProject node) {
return _makeSelect(node);
}
public static SqlOpTable makeSelectOrTable(SqlOpTable node) {
String alias = aliasGenerator.next();
SqlOpTable result = new SqlOpTable(node.getSchema(), node.getTableName(), alias);
return result;
}
public static SqlOpQuery makeSelectOrTable(SqlOpQuery node) {
String alias = aliasGenerator.next();
SqlOpQuery result = new SqlOpQuery(node.getSchema(), node.getQueryString(), alias);
return result;
}
/*
public static SqlOp makeSelectOrTable(SqlAlias node) {
SqlOp tmp = _makeSelectOrTable(node.getSubOp());
SqlAlias result = new SqlAlias(node.getAliasName(), tmp);
copyProjection(result, node);
return result;
}
*/
public static SqlOp makeSelectOrTable(SqlOpFilter node) {
return _makeSelect(node);
}
public static SqlOp makeSelectOrTable(SqlOpSlice node) {
return _makeSelect(node);
}
public static SqlOp makeSelectOrTable(SqlOpDistinct node) {
return _makeSelect(node);
}
public static SqlOp makeSelectOrTable(SqlOpRename op) {
return _makeSelect(op);
}
public static SqlOp makeSelectOrTable(SqlOpJoin node) {
SqlOp left = _makeSelectOrTable(node.getLeft());
SqlOp right = _makeSelectOrTable(node.getRight());
SqlOpJoin join = SqlOpJoin.create(node.getJoinType(), left, right);
join.getConditions().addAll(node.getConditions());
//copyProjection(join, node);
return join;
}
public static SqlOp makeSelectOrTable(SqlOpUnionN node) {
return makeSelect(node);
}
}