diff --git a/src/qir/ast/QIRDBNode.java b/src/qir/ast/QIRDBNode.java index fdc34900558f32bb1908f6ff41a21262ca102532..4c8230d434dfcba69eb7a31f94b91770ad8d9fdf 100644 --- a/src/qir/ast/QIRDBNode.java +++ b/src/qir/ast/QIRDBNode.java @@ -36,7 +36,7 @@ public final class QIRDBNode<DBRepr> extends QIRNode { */ public QIRDBNode(final DBDriver<DBRepr> driver, final QIRNode toTranslate) throws NoSuchElementException { super(toTranslate.sourceSection); - setType(toTranslate.getType().get(), toTranslate.getTypeDriver()); + toTranslate.getType().ifPresent(t -> setType(t, toTranslate.getTypeDriver())); this.driver = driver; this.translation = driver.translate(toTranslate); } @@ -45,6 +45,10 @@ public final class QIRDBNode<DBRepr> extends QIRNode { return translation; } + public final DBDriver<DBRepr> getDriver() { + return driver; + } + @Override public final String toString() { return "DBNode(" + translation + ")"; diff --git a/src/qir/driver/QIRGenericTranslation.java b/src/qir/driver/QIRGenericTranslation.java index 2c8152be8c4d673df6e43bbc4299fa00eafa7c44..9197f25b112ba9306528285b204c8a4ee8343689 100644 --- a/src/qir/driver/QIRGenericTranslation.java +++ b/src/qir/driver/QIRGenericTranslation.java @@ -65,7 +65,14 @@ final class QIRGenericTranslation implements IQIRVisitor<QIRNode> { public final QIRNode visit(final QIRProject qirProject) { if (!(qirProject.getTypeDriver() instanceof MEMDriver)) return new QIRDBNode<>(qirProject.getTypeDriver(), qirProject); - return new QIRProject(qirProject.getSourceSection(), qirProject.getFormatter().accept(this), qirProject.getChild().accept(this)); + final QIRNode child = qirProject.getChild().accept(this); + + if (child instanceof QIRDBNode) + try { + return new QIRDBNode<>(((QIRDBNode<?>) child).getDriver(), new QIRProject(qirProject.getSourceSection(), qirProject.getFormatter(), child)); + } catch (QIRException e) { + } + return new QIRProject(qirProject.getSourceSection(), qirProject.getFormatter().accept(this), child); } @Override @@ -77,6 +84,13 @@ final class QIRGenericTranslation implements IQIRVisitor<QIRNode> { public final QIRNode visit(final QIRFilter qirFilter) { if (!(qirFilter.getTypeDriver() instanceof MEMDriver)) return new QIRDBNode<>(qirFilter.getTypeDriver(), qirFilter); + final QIRNode child = qirFilter.getChild().accept(this); + + if (child instanceof QIRDBNode) + try { + return new QIRDBNode<>(((QIRDBNode<?>) child).getDriver(), new QIRFilter(qirFilter.getSourceSection(), qirFilter.getFilter(), child)); + } catch (QIRException e) { + } return new QIRFilter(qirFilter.getSourceSection(), qirFilter.getFilter().accept(this), qirFilter.getChild().accept(this)); } @@ -84,6 +98,13 @@ final class QIRGenericTranslation implements IQIRVisitor<QIRNode> { public final QIRNode visit(final QIRGroupBy qirGroupBy) { if (!(qirGroupBy.getTypeDriver() instanceof MEMDriver)) return new QIRDBNode<>(qirGroupBy.getTypeDriver(), qirGroupBy); + final QIRNode child = qirGroupBy.getChild().accept(this); + + if (child instanceof QIRDBNode) + try { + return new QIRDBNode<>(((QIRDBNode<?>) child).getDriver(), new QIRGroupBy(qirGroupBy.getSourceSection(), qirGroupBy.getGroup(), child)); + } catch (QIRException e) { + } return new QIRGroupBy(qirGroupBy.getSourceSection(), qirGroupBy.getGroup().accept(this), qirGroupBy.getChild().accept(this)); } @@ -91,6 +112,13 @@ final class QIRGenericTranslation implements IQIRVisitor<QIRNode> { public final QIRNode visit(final QIRSortBy qirSortBy) { if (!(qirSortBy.getTypeDriver() instanceof MEMDriver)) return new QIRDBNode<>(qirSortBy.getTypeDriver(), qirSortBy); + final QIRNode child = qirSortBy.getChild().accept(this); + + if (child instanceof QIRDBNode) + try { + return new QIRDBNode<>(((QIRDBNode<?>) child).getDriver(), new QIRSortBy(qirSortBy.getSourceSection(), qirSortBy.getSort(), qirSortBy.getIsAscending(), child)); + } catch (QIRException e) { + } return new QIRSortBy(qirSortBy.getSourceSection(), qirSortBy.getSort().accept(this), qirSortBy.getIsAscending().accept(this), qirSortBy.getChild().accept(this)); } @@ -124,7 +152,7 @@ final class QIRGenericTranslation implements IQIRVisitor<QIRNode> { @Override public final <DBRepr> QIRNode visit(final QIRDBNode<DBRepr> qirDBNode) { - throw new QIRException("Should not visit QIRDBNode in generic translation."); + return qirDBNode; } @Override diff --git a/src/qir/driver/hbase/HBaseDriver.java b/src/qir/driver/hbase/HBaseDriver.java index 903d37c2c73a643afbd5a731672c0ade1d5702d9..4f9fac14c7195c277f68ebf908e7b31b0d75b749 100644 --- a/src/qir/driver/hbase/HBaseDriver.java +++ b/src/qir/driver/hbase/HBaseDriver.java @@ -85,7 +85,7 @@ public final class HBaseDriver extends DBDriver<HBaseQuery> { @Override public HBaseQuery translate(final QIRNode query) { - return query.accept(new HBaseQueryTranslator(conf)); + return query.accept(new HBaseQueryTranslator(conf, dbName, configFile)); } @Override diff --git a/src/qir/driver/hbase/HBaseQueryTranslator.java b/src/qir/driver/hbase/HBaseQueryTranslator.java index cedf413b94ad9628703ce26eabe3353bb6a3c0f6..a24e88c9576321f35c9f6cbe9229c516a0d4f77e 100644 --- a/src/qir/driver/hbase/HBaseQueryTranslator.java +++ b/src/qir/driver/hbase/HBaseQueryTranslator.java @@ -24,9 +24,13 @@ import qir.util.QIRException; */ final class HBaseQueryTranslator extends QIRTranslator<HBaseQuery> { private final Configuration conf; + private final String dbName; + private final String dbConfig; - HBaseQueryTranslator(final Configuration conf) { + HBaseQueryTranslator(final Configuration conf, final String dbName, final String dbConfig) { this.conf = conf; + this.dbName = dbName; + this.dbConfig = dbConfig; } @Override @@ -43,6 +47,9 @@ final class HBaseQueryTranslator extends QIRTranslator<HBaseQuery> { @Override public final HBaseQuery visit(QIRScan qirScan) { if (qirScan.getTable() instanceof QIRTable && ((QIRTable) qirScan.getTable()).getDbName() instanceof QIRString && ((QIRTable) qirScan.getTable()).getConfigFile() instanceof QIRString) { + final QIRTable table = (QIRTable) qirScan.getTable(); + if (!((QIRString) table.getDbName()).getValue().equals(dbName) || !((QIRString) table.getConfigFile()).getValue().equals(dbConfig)) + throw new QIRException("Subquery for another database detected."); return new HBaseQuery(new Scan(), (String) ((QIRBaseValue<?>) ((QIRTable) qirScan.getTable()).getSchemaName()).getValue() + ":" + (String) ((QIRBaseValue<?>) ((QIRTable) qirScan.getTable()).getTableName()).getValue()); } diff --git a/src/qir/driver/sql/HiveDriver.java b/src/qir/driver/sql/HiveDriver.java index e7521c63f90183a1560f3d461be1fa46a51df36e..64258e65765ff5cb30526ceb98c3836477f527de 100644 --- a/src/qir/driver/sql/HiveDriver.java +++ b/src/qir/driver/sql/HiveDriver.java @@ -17,7 +17,7 @@ public final class HiveDriver extends SQLStringDriver { @Override public String translate(final QIRNode query) { - return query.accept(new HiveStringTranslator()); + return query.accept(new HiveStringTranslator(dbName, configFile)); } @Override diff --git a/src/qir/driver/sql/HiveStringTranslator.java b/src/qir/driver/sql/HiveStringTranslator.java index de042f838d93981fb301059b7ecc224092693e27..f11436997a063eb67c7e4c6f64bd750acaa8958d 100644 --- a/src/qir/driver/sql/HiveStringTranslator.java +++ b/src/qir/driver/sql/HiveStringTranslator.java @@ -19,6 +19,10 @@ import qir.ast.operator.QIROperator; import qir.util.QIRException; public class HiveStringTranslator extends SQLStringTranslator { + public HiveStringTranslator(String dbName, String dbConfig) { + super(dbName, dbConfig); + } + @Override public final String visit(final QIRApply qirApply) { // TODO: Improve implementation diff --git a/src/qir/driver/sql/OracleDriver.java b/src/qir/driver/sql/OracleDriver.java index a5ed8ada87c55409f4b056357dc8a538e5703d3a..8d396b46b2d1a8155b50b6c7aab37540873be077 100644 --- a/src/qir/driver/sql/OracleDriver.java +++ b/src/qir/driver/sql/OracleDriver.java @@ -12,7 +12,7 @@ import qir.util.QIRException; */ public final class OracleDriver extends SQLStringDriver { public static final String dbName = "Oracle"; - private static final SQLStringTranslator translator = new SQLStringTranslator(); + private final SQLStringTranslator translator = new SQLStringTranslator(dbName, configFile); public OracleDriver(final String configFile) { super(configFile); diff --git a/src/qir/driver/sql/PostgreSQLDriver.java b/src/qir/driver/sql/PostgreSQLDriver.java index fb331afefbefc2dacd77c227b1fd4e1a5f98b85e..6f363280f1c9d06debf52715c6f3feb2e2db3f05 100644 --- a/src/qir/driver/sql/PostgreSQLDriver.java +++ b/src/qir/driver/sql/PostgreSQLDriver.java @@ -18,7 +18,7 @@ public final class PostgreSQLDriver extends SQLStringDriver { @Override public String translate(final QIRNode query) { - return query.accept(new SQLStringTranslator()); + return query.accept(new SQLStringTranslator(dbName, configFile)); } @Override diff --git a/src/qir/driver/sql/SQLStringTranslator.java b/src/qir/driver/sql/SQLStringTranslator.java index fb24e821fca8029bfe5912cf699c413315d9c600..00ab38921db0d33861238e85d9a10b83534a7ad2 100644 --- a/src/qir/driver/sql/SQLStringTranslator.java +++ b/src/qir/driver/sql/SQLStringTranslator.java @@ -35,6 +35,21 @@ public class SQLStringTranslator extends QIRTranslator<String> { */ private Map<String, String> prolog = new HashMap<>(); + /** + * The name of the database the query will be sent to. + */ + private final String dbName; + + /** + * The configuration file of the database the query will be sent to. + */ + private final String dbConfig; + + public SQLStringTranslator(final String dbName, final String dbConfig) { + this.dbName = dbName; + this.dbConfig = dbConfig; + } + public final Map<String, String> popProlog() { final Map<String, String> res = prolog; prolog = new HashMap<>(); @@ -51,8 +66,12 @@ public class SQLStringTranslator extends QIRTranslator<String> { @Override public final String visit(final QIRScan qirScan) { - if (qirScan.getTable() instanceof QIRTable && ((QIRTable) qirScan.getTable()).getDbName() instanceof QIRString && ((QIRTable) qirScan.getTable()).getConfigFile() instanceof QIRString) + if (qirScan.getTable() instanceof QIRTable && ((QIRTable) qirScan.getTable()).getDbName() instanceof QIRString && ((QIRTable) qirScan.getTable()).getConfigFile() instanceof QIRString) { + final QIRTable table = (QIRTable) qirScan.getTable(); + if (!((QIRString) table.getDbName()).getValue().equals(dbName) || !((QIRString) table.getConfigFile()).getValue().equals(dbConfig)) + throw new QIRException("Subquery for another database detected."); return "select * from " + qirScan.getTable().accept(this); + } throw new QIRException("QIR SQL Scan not implemented for table type: " + qirScan.getTable().getClass()); } diff --git a/src/qir/types/QIRFunctionType.java b/src/qir/types/QIRFunctionType.java index a6ab8bb93d2f960872a874dcffba4f921143a409..cc545f6fee4d5bc11e55587a79a5dc590bbaba55 100644 --- a/src/qir/types/QIRFunctionType.java +++ b/src/qir/types/QIRFunctionType.java @@ -39,6 +39,7 @@ public final class QIRFunctionType extends QIRType { } @Override + /* TODO: Fix contravariance */ protected final boolean isSubtypeOfAux(final QIRType other) { return other instanceof QIRFunctionType && argumentType.isSubtypeOf(((QIRFunctionType) other).argumentType) && returnType.isSubtypeOf(((QIRFunctionType) other).returnType); } diff --git a/src/qir/typing/QIRSpecificTypeSystem.java b/src/qir/typing/QIRSpecificTypeSystem.java index 5ec55ebcabd5c64fb04f5d51db03c8cc7f468a55..cc5fc8608ba7f062b64161787321a1cffcaae043 100644 --- a/src/qir/typing/QIRSpecificTypeSystem.java +++ b/src/qir/typing/QIRSpecificTypeSystem.java @@ -153,7 +153,8 @@ public abstract class QIRSpecificTypeSystem extends QIRTypeSystem { /** * Throws a {@link QIRTypeErrorException} if the actual {@link QIRType} and the expected * {@link QIRType} do not share a common subtype in the sense of - * {@link QIRType#isSubtypeOf(QIRType)}. + * {@link QIRType#isSubtypeOf(QIRType)}. TODO: Fix implementation or change name to + * checkEitherSubtype. * * @param actual The actual {@link QIRType} of the expression. * @param expected The expected {@link QIRType} for the expression.