📄 select.java
字号:
Index columnIndex = topTableFilter.getTable().getIndexForColumn(column, true);
if (columnIndex != null && selectivity != Constants.SELECTIVITY_DEFAULT && selectivity < 20) {
// the first column must be ascending
boolean ascending = columnIndex.getIndexColumns()[0].sortType == SortOrder.ASCENDING;
Index current = topTableFilter.getIndex();
// if another index is faster
if (columnIndex.canFindNext() && ascending && (current == null || current.getIndexType().isScan() || columnIndex == current)) {
IndexType type = columnIndex.getIndexType();
// hash indexes don't work, and unique single column indexes don't work
if (!type.isHash() && (!type.isUnique() || columnIndex.getColumns().length > 1)) {
topTableFilter.setIndex(columnIndex);
isDistinctQuery = true;
}
}
}
}
}
if (sort != null && !isQuickQuery && !isGroupQuery) {
Index index = getSortIndex();
Index current = topTableFilter.getIndex();
if (index != null && (current.getIndexType().isScan() || current == index)) {
topTableFilter.setIndex(index);
if (!distinct || isDistinctQuery) {
// sort using index would not work correctly for distinct result sets
// because it would break too early when limit is used
sortUsingIndex = true;
}
}
}
if (SysProperties.OPTIMIZE_GROUP_SORTED && !isQuickQuery && isGroupQuery && getGroupByExpressionCount() > 0) {
Index index = getGroupSortedIndex();
Index current = topTableFilter.getIndex();
if (index != null && (current.getIndexType().isScan() || current == index)) {
topTableFilter.setIndex(index);
isGroupSortedQuery = true;
}
}
isPrepared = true;
}
public double getCost() {
return cost;
}
public HashSet getTables() {
HashSet set = new HashSet();
for (int i = 0; i < filters.size(); i++) {
TableFilter filter = (TableFilter) filters.get(i);
set.add(filter.getTable());
}
return set;
}
private double preparePlan() throws SQLException {
TableFilter[] topArray = new TableFilter[topFilters.size()];
topFilters.toArray(topArray);
for (int i = 0; i < topArray.length; i++) {
topArray[i].setFullCondition(condition);
}
Optimizer optimizer = new Optimizer(topArray, condition, session);
optimizer.optimize();
topTableFilter = optimizer.getTopFilter();
double cost = optimizer.getCost();
TableFilter f = topTableFilter;
while (f != null) {
f.setEvaluatable(f, true);
if (condition != null) {
condition.setEvaluatable(f, true);
}
Expression on = f.getJoinCondition();
if (on != null) {
if (!on.isEverything(ExpressionVisitor.EVALUATABLE)) {
if (f.isJoinOuter()) {
throw Message.getSQLException(ErrorCode.UNSUPPORTED_OUTER_JOIN_CONDITION_1, on.getSQL());
}
f.removeJoinCondition();
// need to check that all added are bound to a table
on = on.optimize(session);
addCondition(on);
}
}
on = f.getFilterCondition();
if (on != null) {
if (!on.isEverything(ExpressionVisitor.EVALUATABLE)) {
f.removeFilterCondition();
addCondition(on);
}
}
// this is only important for subqueries, so they know
// the result columns are evaluatable
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
e.setEvaluatable(f, true);
}
f = f.getJoin();
}
topTableFilter.prepare();
return cost;
}
public String getPlanSQL() {
if (topTableFilter == null) {
return sql;
}
StringBuffer buff = new StringBuffer();
Expression[] exprList = new Expression[expressions.size()];
expressions.toArray(exprList);
buff.append("SELECT ");
if (distinct) {
buff.append("DISTINCT ");
}
for (int i = 0; i < visibleColumnCount; i++) {
if (i > 0) {
buff.append(", ");
}
Expression expr = exprList[i];
buff.append(expr.getSQL());
}
buff.append("\nFROM ");
TableFilter filter = topTableFilter;
boolean join = false;
int id = 0;
do {
if (id > 0) {
buff.append("\n");
}
buff.append(filter.getPlanSQL(join));
id++;
join = true;
filter = filter.getJoin();
} while (filter != null);
if (condition != null) {
buff.append("\nWHERE " + StringUtils.unEnclose(condition.getSQL()));
}
if (groupIndex != null) {
buff.append("\nGROUP BY ");
for (int i = 0; i < groupIndex.length; i++) {
Expression g = exprList[groupIndex[i]];
g = g.getNonAliasExpression();
if (i > 0) {
buff.append(", ");
}
buff.append(StringUtils.unEnclose(g.getSQL()));
}
}
if (having != null) {
// could be set in addGlobalCondition
// in this case the query is not run directly, just getPlanSQL is
// called
Expression h = having;
buff.append("\nHAVING " + StringUtils.unEnclose(h.getSQL()));
} else if (havingIndex >= 0) {
Expression h = exprList[havingIndex];
buff.append("\nHAVING " + StringUtils.unEnclose(h.getSQL()));
}
if (sort != null) {
buff.append("\nORDER BY ");
buff.append(sort.getSQL(exprList, visibleColumnCount));
}
if (limit != null) {
buff.append("\nLIMIT ");
buff.append(StringUtils.unEnclose(limit.getSQL()));
if (offset != null) {
buff.append(" OFFSET ");
buff.append(StringUtils.unEnclose(offset.getSQL()));
}
}
if (isForUpdate) {
buff.append("\nFOR UPDATE");
}
if (isQuickQuery) {
buff.append("\n/* direct lookup */");
}
if (isDistinctQuery) {
buff.append("\n/* distinct */");
}
if (isGroupQuery) {
if (isGroupSortedQuery) {
buff.append("\n/* group sorted */");
}
}
return buff.toString();
}
public void setDistinct(boolean b) {
distinct = b;
}
public void setHaving(Expression having) {
this.having = having;
}
public int getColumnCount() {
return visibleColumnCount;
}
public TableFilter getTopTableFilter() {
return topTableFilter;
}
public ObjectArray getExpressions() {
return expressions;
}
public void setForUpdate(boolean b) {
this.isForUpdate = b;
}
public void mapColumns(ColumnResolver resolver, int level) throws SQLException {
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
e.mapColumns(resolver, level);
}
if (condition != null) {
condition.mapColumns(resolver, level);
}
}
public void setEvaluatable(TableFilter tableFilter, boolean b) {
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
e.setEvaluatable(tableFilter, b);
}
if (condition != null) {
condition.setEvaluatable(tableFilter, b);
}
}
public boolean isQuickQuery() {
return isQuickQuery;
}
public void addGlobalCondition(Parameter param, int columnId, int comparisonType) throws SQLException {
addParameter(param);
Expression col = (Expression) expressions.get(columnId);
col = col.getNonAliasExpression();
Expression comp = new Comparison(session, comparisonType, col, param);
comp = comp.optimize(session);
boolean addToCondition = true;
if (isGroupQuery) {
addToCondition = false;
for (int i = 0; groupIndex != null && i < groupIndex.length; i++) {
if (groupIndex[i] == columnId) {
addToCondition = true;
break;
}
}
if (!addToCondition) {
if (havingIndex >= 0) {
having = (Expression) expressions.get(havingIndex);
}
if (having == null) {
having = comp;
} else {
having = new ConditionAndOr(ConditionAndOr.AND, having, comp);
}
}
}
if (addToCondition) {
if (condition == null) {
condition = comp;
} else {
condition = new ConditionAndOr(ConditionAndOr.AND, condition, comp);
}
}
}
public void updateAggregate(Session session) throws SQLException {
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
e.updateAggregate(session);
}
if (condition != null) {
condition.updateAggregate(session);
}
if (having != null) {
having.updateAggregate(session);
}
}
public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.type) {
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: {
for (int i = 0; i < filters.size(); i++) {
TableFilter f = (TableFilter) filters.get(i);
long m = f.getTable().getMaxDataModificationId();
visitor.addDataModificationId(m);
}
break;
}
case ExpressionVisitor.EVALUATABLE: {
if (!SysProperties.OPTIMIZE_EVALUATABLE_SUBQUERIES) {
return false;
}
break;
}
case ExpressionVisitor.GET_DEPENDENCIES: {
for (int i = 0; i < filters.size(); i++) {
TableFilter filter = (TableFilter) filters.get(i);
Table table = filter.getTable();
visitor.addDependency(table);
table.addDependencies(visitor.getDependencies());
}
break;
}
}
visitor.queryLevel(1);
boolean result = true;
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
if (!e.isEverything(visitor)) {
result = false;
break;
}
}
if (result && condition != null && !condition.isEverything(visitor)) {
result = false;
}
if (result && having != null && !having.isEverything(visitor)) {
result = false;
}
visitor.queryLevel(-1);
return result;
}
public boolean isReadOnly() {
return isEverything(ExpressionVisitor.READONLY);
}
public String getFirstColumnAlias(Session session) {
if (SysProperties.CHECK) {
if (visibleColumnCount > 1) {
throw Message.getInternalError("" + visibleColumnCount);
}
}
Expression expr = (Expression) expressions.get(0);
if (expr instanceof Alias) {
return expr.getAlias();
} else {
expr = new Alias(expr, session.getNextTempViewName() + "_X");
expressions.set(0, expr);
}
return expr.getAlias();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -