Unverified 提交 cacef49b authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #902 from katzyn/nested_joins

Remove DbSettings.nestedJoins
...@@ -1368,14 +1368,9 @@ public class Parser { ...@@ -1368,14 +1368,9 @@ public class Parser {
query, currentSelect); query, currentSelect);
} else { } else {
TableFilter top; TableFilter top;
if (database.getSettings().nestedJoins) { top = readTableFilter(false);
top = readTableFilter(false); top = readJoin(top, currentSelect, false, false);
top = readJoin(top, currentSelect, false, false); top = getNested(top);
top = getNested(top);
} else {
top = readTableFilter(fromOuter);
top = readJoin(top, currentSelect, false, fromOuter);
}
read(")"); read(")");
alias = readFromAlias(null); alias = readFromAlias(null);
if (alias != null) { if (alias != null) {
...@@ -1726,88 +1721,57 @@ public class Parser { ...@@ -1726,88 +1721,57 @@ public class Parser {
boolean nested, boolean fromOuter) { boolean nested, boolean fromOuter) {
boolean joined = false; boolean joined = false;
TableFilter last = top; TableFilter last = top;
boolean nestedJoins = database.getSettings().nestedJoins;
while (true) { while (true) {
TableFilter join;
if (readIf("RIGHT")) { if (readIf("RIGHT")) {
readIf("OUTER"); readIf("OUTER");
read("JOIN"); read("JOIN");
joined = true;
// the right hand side is the 'inner' table usually // the right hand side is the 'inner' table usually
TableFilter newTop = readTableFilter(fromOuter); join = readTableFilter(fromOuter);
newTop = readJoin(newTop, command, nested, true); join = readJoin(join, command, nested, true);
Expression on = null; Expression on = null;
if (readIf("ON")) { if (readIf("ON")) {
on = readExpression(); on = readExpression();
} }
if (nestedJoins) { top = getNested(top);
top = getNested(top); join.addJoin(top, true, false, on);
newTop.addJoin(top, true, false, on); top = join;
} else {
newTop.addJoin(top, true, false, on);
}
top = newTop;
last = newTop;
} else if (readIf("LEFT")) { } else if (readIf("LEFT")) {
readIf("OUTER"); readIf("OUTER");
read("JOIN"); read("JOIN");
joined = true; join = readTableFilter(true);
TableFilter join = readTableFilter(true); join = readJoin(join, command, true, true);
if (nestedJoins) {
join = readJoin(join, command, true, true);
} else {
top = readJoin(top, command, false, true);
}
Expression on = null; Expression on = null;
if (readIf("ON")) { if (readIf("ON")) {
on = readExpression(); on = readExpression();
} }
top.addJoin(join, true, false, on); top.addJoin(join, true, false, on);
last = join;
} else if (readIf("FULL")) { } else if (readIf("FULL")) {
throw getSyntaxError(); throw getSyntaxError();
} else if (readIf("INNER")) { } else if (readIf("INNER")) {
read("JOIN"); read("JOIN");
joined = true; join = readTableFilter(fromOuter);
TableFilter join = readTableFilter(fromOuter);
top = readJoin(top, command, false, false); top = readJoin(top, command, false, false);
Expression on = null; Expression on = null;
if (readIf("ON")) { if (readIf("ON")) {
on = readExpression(); on = readExpression();
} }
if (nestedJoins) { top.addJoin(join, false, false, on);
top.addJoin(join, false, false, on);
} else {
top.addJoin(join, fromOuter, false, on);
}
last = join;
} else if (readIf("JOIN")) { } else if (readIf("JOIN")) {
joined = true; join = readTableFilter(fromOuter);
TableFilter join = readTableFilter(fromOuter);
top = readJoin(top, command, false, false); top = readJoin(top, command, false, false);
Expression on = null; Expression on = null;
if (readIf("ON")) { if (readIf("ON")) {
on = readExpression(); on = readExpression();
} }
if (nestedJoins) { top.addJoin(join, false, false, on);
top.addJoin(join, false, false, on);
} else {
top.addJoin(join, fromOuter, false, on);
}
last = join;
} else if (readIf("CROSS")) { } else if (readIf("CROSS")) {
read("JOIN"); read("JOIN");
joined = true; join = readTableFilter(fromOuter);
TableFilter join = readTableFilter(fromOuter); top.addJoin(join, false, false, null);
if (nestedJoins) {
top.addJoin(join, false, false, null);
} else {
top.addJoin(join, fromOuter, false, null);
}
last = join;
} else if (readIf("NATURAL")) { } else if (readIf("NATURAL")) {
read("JOIN"); read("JOIN");
joined = true; join = readTableFilter(fromOuter);
TableFilter join = readTableFilter(fromOuter);
Column[] tableCols = last.getTable().getColumns(); Column[] tableCols = last.getTable().getColumns();
Column[] joinCols = join.getTable().getColumns(); Column[] joinCols = join.getTable().getColumns();
String tableSchema = last.getTable().getSchema().getName(); String tableSchema = last.getTable().getSchema().getName();
...@@ -1836,15 +1800,12 @@ public class Parser { ...@@ -1836,15 +1800,12 @@ public class Parser {
} }
} }
} }
if (nestedJoins) { top.addJoin(join, false, nested, on);
top.addJoin(join, false, nested, on);
} else {
top.addJoin(join, fromOuter, false, on);
}
last = join;
} else { } else {
break; break;
} }
joined = true;
last = join;
} }
if (nested && joined) { if (nested && joined) {
top = getNested(top); top = getNested(top);
......
...@@ -1046,26 +1046,10 @@ public class Select extends Query { ...@@ -1046,26 +1046,10 @@ public class Select extends Query {
Expression on = f.getJoinCondition(); Expression on = f.getJoinCondition();
if (on != null) { if (on != null) {
if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) { if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
if (session.getDatabase().getSettings().nestedJoins) { // need to check that all added are bound to a table
// need to check that all added are bound to a table on = on.optimize(session);
on = on.optimize(session); if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) {
if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) {
f.removeJoinCondition();
addCondition(on);
}
} else {
if (f.isJoinOuter()) {
// this will check if all columns exist - it may or
// may not throw an exception
on = on.optimize(session);
// it is not supported even if the columns exist
throw DbException.get(
ErrorCode.UNSUPPORTED_OUTER_JOIN_CONDITION_1,
on.getSQL());
}
f.removeJoinCondition(); f.removeJoinCondition();
// need to check that all added are bound to a table
on = on.optimize(session);
addCondition(on); addCondition(on);
} }
} }
......
...@@ -7,6 +7,9 @@ package org.h2.engine; ...@@ -7,6 +7,9 @@ package org.h2.engine;
import java.util.HashMap; import java.util.HashMap;
import org.h2.message.DbException;
import org.h2.util.Utils;
/** /**
* This class contains various database-level settings. To override the * This class contains various database-level settings. To override the
* documented default value for a database, append the setting in the database * documented default value for a database, append the setting in the database
...@@ -164,12 +167,6 @@ public class DbSettings extends SettingsBase { ...@@ -164,12 +167,6 @@ public class DbSettings extends SettingsBase {
*/ */
public final int maxQueryTimeout = get("MAX_QUERY_TIMEOUT", 0); public final int maxQueryTimeout = get("MAX_QUERY_TIMEOUT", 0);
/**
* Database setting <code>NESTED_JOINS</code> (default: true).<br />
* Whether nested joins should be supported.
*/
public final boolean nestedJoins = get("NESTED_JOINS", true);
/** /**
* Database setting <code>OPTIMIZE_DISTINCT</code> (default: true).<br /> * Database setting <code>OPTIMIZE_DISTINCT</code> (default: true).<br />
* Improve the performance of simple DISTINCT queries if an index is * Improve the performance of simple DISTINCT queries if an index is
...@@ -363,6 +360,9 @@ public class DbSettings extends SettingsBase { ...@@ -363,6 +360,9 @@ public class DbSettings extends SettingsBase {
private DbSettings(HashMap<String, String> s) { private DbSettings(HashMap<String, String> s) {
super(s); super(s);
if (s.get("NESTED_JOINS") != null || Utils.getProperty("h2.nestedJoins", null) != null) {
throw DbException.getUnsupportedException("NESTED_JOINS setting is not available since 1.4.197");
}
} }
/** /**
......
...@@ -37,7 +37,6 @@ public class ExpressionColumn extends Expression { ...@@ -37,7 +37,6 @@ public class ExpressionColumn extends Expression {
private ColumnResolver columnResolver; private ColumnResolver columnResolver;
private int queryLevel; private int queryLevel;
private Column column; private Column column;
private boolean evaluatable;
public ExpressionColumn(Database database, Column column) { public ExpressionColumn(Database database, Column column) {
this.database = database; this.database = database;
...@@ -205,9 +204,6 @@ public class ExpressionColumn extends Expression { ...@@ -205,9 +204,6 @@ public class ExpressionColumn extends Expression {
@Override @Override
public void setEvaluatable(TableFilter tableFilter, boolean b) { public void setEvaluatable(TableFilter tableFilter, boolean b) {
if (columnResolver != null && tableFilter == columnResolver.getTableFilter()) {
evaluatable = b;
}
} }
public Column getColumn() { public Column getColumn() {
...@@ -287,19 +283,15 @@ public class ExpressionColumn extends Expression { ...@@ -287,19 +283,15 @@ public class ExpressionColumn extends Expression {
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
return this.queryLevel < visitor.getQueryLevel(); return this.queryLevel < visitor.getQueryLevel();
case ExpressionVisitor.EVALUATABLE: case ExpressionVisitor.EVALUATABLE:
// if the current value is known (evaluatable set) // if this column belongs to a 'higher level' query and is
// or if this columns belongs to a 'higher level' query and is
// therefore just a parameter // therefore just a parameter
if (database.getSettings().nestedJoins) { if (visitor.getQueryLevel() < this.queryLevel) {
if (visitor.getQueryLevel() < this.queryLevel) { return true;
return true; }
} if (getTableFilter() == null) {
if (getTableFilter() == null) { return false;
return false;
}
return getTableFilter().isEvaluatable();
} }
return evaluatable || visitor.getQueryLevel() < this.queryLevel; return getTableFilter().isEvaluatable();
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
visitor.addDataModificationId(column.getTable().getMaxDataModificationId()); visitor.addDataModificationId(column.getTable().getMaxDataModificationId());
return true; return true;
......
...@@ -230,14 +230,14 @@ public class TableFilter implements ColumnResolver { ...@@ -230,14 +230,14 @@ public class TableFilter implements ColumnResolver {
} }
if (nestedJoin != null) { if (nestedJoin != null) {
setEvaluatable(nestedJoin); setEvaluatable(true);
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, filters, filter, allColumnsSet)); item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, filters, filter, allColumnsSet));
// TODO optimizer: calculate cost of a join: should use separate // TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost // expected row number and lookup cost
item.cost += item.cost * item.getNestedJoinPlan().cost; item.cost += item.cost * item.getNestedJoinPlan().cost;
} }
if (join != null) { if (join != null) {
setEvaluatable(join); setEvaluatable(true);
do { do {
filter++; filter++;
} while (filters[filter] != join); } while (filters[filter] != join);
...@@ -249,25 +249,6 @@ public class TableFilter implements ColumnResolver { ...@@ -249,25 +249,6 @@ public class TableFilter implements ColumnResolver {
return item; return item;
} }
private void setEvaluatable(TableFilter join) {
if (session.getDatabase().getSettings().nestedJoins) {
setEvaluatable(true);
return;
}
// this table filter is now evaluatable - in all sub-joins
do {
Expression e = join.getJoinCondition();
if (e != null) {
e.setEvaluatable(this, true);
}
TableFilter n = join.getNestedJoin();
if (n != null) {
setEvaluatable(n);
}
join = join.getJoin();
} while (join != null);
}
/** /**
* Set what plan item (index, cost, masks) to use. * Set what plan item (index, cost, masks) to use.
* *
...@@ -663,13 +644,11 @@ public class TableFilter implements ColumnResolver { ...@@ -663,13 +644,11 @@ public class TableFilter implements ColumnResolver {
final Expression on) { final Expression on) {
if (on != null) { if (on != null) {
on.mapColumns(this, 0); on.mapColumns(this, 0);
if (session.getDatabase().getSettings().nestedJoins) { TableFilterVisitor visitor = new MapColumnsVisitor(on);
TableFilterVisitor visitor = new MapColumnsVisitor(on); visit(visitor);
visit(visitor); filter.visit(visitor);
filter.visit(visitor);
}
} }
if (nested && session.getDatabase().getSettings().nestedJoins) { if (nested) {
if (nestedJoin != null) { if (nestedJoin != null) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
...@@ -685,20 +664,8 @@ public class TableFilter implements ColumnResolver { ...@@ -685,20 +664,8 @@ public class TableFilter implements ColumnResolver {
if (join == null) { if (join == null) {
join = filter; join = filter;
filter.joinOuter = outer; filter.joinOuter = outer;
if (session.getDatabase().getSettings().nestedJoins) { if (outer) {
if (outer) { filter.visit(new JOIVisitor());
filter.visit(new JOIVisitor());
}
} else {
if (outer) {
// convert all inner joins on the right hand side to
// outer joins
TableFilter f = filter.join;
while (f != null) {
f.joinOuter = true;
f = f.join;
}
}
} }
if (on != null) { if (on != null) {
filter.mapAndAddFilter(on); filter.mapAndAddFilter(on);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论