select.java
来自「非常棒的java数据库」· Java 代码 · 共 1,052 行 · 第 1/3 页
JAVA
1,052 行
if (sort == null) {
return null;
}
int[] indexes = sort.getIndexes();
ObjectArray sortColumns = new ObjectArray();
for (int i = 0; i < indexes.length; i++) {
int idx = indexes[i];
if (idx < 0 || idx >= expressions.size()) {
throw Message.getInvalidValueException("" + (idx + 1), "ORDER BY");
}
Expression expr = (Expression) expressions.get(idx);
expr = expr.getNonAliasExpression();
if (expr.isConstant()) {
continue;
}
if (!(expr instanceof ExpressionColumn)) {
return null;
}
Column col = ((ExpressionColumn) expr).getColumn();
if (col.getTable() != topTableFilter.getTable()) {
return null;
}
sortColumns.add(col);
}
Column[] sortCols = new Column[sortColumns.size()];
sortColumns.toArray(sortCols);
int[] sortTypes = sort.getSortTypes();
if (sortCols.length == 0) {
// sort just on constants - can use scan index
return topTableFilter.getTable().getScanIndex(session);
}
ObjectArray list = topTableFilter.getTable().getIndexes();
for (int i = 0; list != null && i < list.size(); i++) {
Index index = (Index) list.get(i);
if (index.getCreateSQL() == null) {
// can't use the scan index
continue;
}
if (index.getIndexType().isHash()) {
continue;
}
IndexColumn[] indexCols = index.getIndexColumns();
if (indexCols.length < sortCols.length) {
continue;
}
boolean ok = true;
for (int j = 0; j < sortCols.length; j++) {
// the index and the sort order must start
// with the exact same columns
IndexColumn idxCol = indexCols[j];
Column sortCol = sortCols[j];
if (idxCol.column != sortCol) {
ok = false;
break;
}
if (idxCol.sortType != sortTypes[j]) {
// TODO NULL FIRST for ascending and NULLS LAST
// for descending would actually match the default
ok = false;
break;
}
}
if (ok) {
return index;
}
}
return null;
}
private void queryDistinct(int columnCount, LocalResult result, long limitRows) throws SQLException {
if (limitRows != 0 && offset != null) {
// limitRows must be long, otherwise we get an int overflow
// if limitRows is at or near Integer.MAX_VALUE
limitRows += offset.getValue(session).getInt();
}
int rowNumber = 0;
setCurrentRowNumber(0);
Index index = topTableFilter.getIndex();
SearchRow first = null;
int columnIndex = index.getColumns()[0].getColumnId();
while (true) {
checkCancelled();
setCurrentRowNumber(rowNumber + 1);
Cursor cursor = index.findNext(session, first, null);
if (!cursor.next()) {
break;
}
SearchRow found = cursor.getSearchRow();
Value value = found.getValue(columnIndex);
if (first == null) {
first = topTableFilter.getTable().getTemplateSimpleRow(true);
}
first.setValue(columnIndex, value);
Value[] row = new Value[1];
row[0] = value;
result.addRow(row);
rowNumber++;
if ((sort == null || sortUsingIndex) && limitRows != 0 && result.getRowCount() >= limitRows) {
break;
}
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
}
}
}
private void queryFlat(int columnCount, LocalResult result, long limitRows) throws SQLException {
if (limitRows != 0 && offset != null) {
// limitRows must be long, otherwise we get an int overflow
// if limitRows is at or near Integer.MAX_VALUE
limitRows += offset.getValue(session).getInt();
}
int rowNumber = 0;
setCurrentRowNumber(0);
while (topTableFilter.next()) {
checkCancelled();
setCurrentRowNumber(rowNumber + 1);
if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
Value[] row = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
Expression expr = (Expression) expressions.get(i);
row[i] = expr.getValue(session);
}
result.addRow(row);
rowNumber++;
if ((sort == null || sortUsingIndex) && limitRows != 0 && result.getRowCount() >= limitRows) {
break;
}
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
}
}
}
}
private void queryQuick(int columnCount, LocalResult result) throws SQLException {
Value[] row = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
Expression expr = (Expression) expressions.get(i);
row[i] = expr.getValue(session);
}
result.addRow(row);
}
public LocalResult queryMeta() throws SQLException {
LocalResult result = new LocalResult(session, expressions, visibleColumnCount);
result.done();
return result;
}
public LocalResult queryWithoutCache(int maxRows) throws SQLException {
int limitRows = maxRows;
if (limit != null) {
int l = limit.getValue(session).getInt();
if (limitRows == 0) {
limitRows = l;
} else {
limitRows = Math.min(l, limitRows);
}
}
int columnCount = expressions.size();
LocalResult result = new LocalResult(session, expressions, visibleColumnCount);
if (!sortUsingIndex) {
result.setSortOrder(sort);
}
if (distinct && !isDistinctQuery) {
result.setDistinct();
}
topTableFilter.startQuery(session);
topTableFilter.reset();
topTableFilter.lock(session, isForUpdate, isForUpdate);
if (isQuickQuery) {
queryQuick(columnCount, result);
} else if (isGroupQuery) {
if (isGroupSortedQuery) {
queryGroupSorted(columnCount, result);
} else {
queryGroup(columnCount, result);
}
} else if (isDistinctQuery) {
queryDistinct(columnCount, result, limitRows);
} else {
queryFlat(columnCount, result, limitRows);
}
if (offset != null) {
result.setOffset(offset.getValue(session).getInt());
}
if (limitRows != 0) {
result.setLimit(limitRows);
}
result.done();
return result;
}
private void expandColumnList() throws SQLException {
// TODO this works: select distinct count(*) from system_columns group
// by table
for (int i = 0; i < expressions.size(); i++) {
Expression expr = (Expression) expressions.get(i);
if (!expr.isWildcard()) {
continue;
}
String tableAlias = expr.getTableAlias();
if (tableAlias == null) {
int temp = i;
expressions.remove(i);
for (int j = 0; j < filters.size(); j++) {
TableFilter filter = (TableFilter) filters.get(j);
Wildcard c2 = new Wildcard(filter.getTable().getSchema().getName(), filter.getTableAlias());
expressions.add(i++, c2);
}
i = temp - 1;
} else {
TableFilter filter = null;
for (int j = 0; j < filters.size(); j++) {
TableFilter f = (TableFilter) filters.get(j);
if (tableAlias.equals(f.getTableAlias())) {
filter = f;
break;
}
}
if (filter == null) {
throw Message.getSQLException(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableAlias);
}
Table t = filter.getTable();
String alias = filter.getTableAlias();
expressions.remove(i);
Column[] columns = t.getColumns();
for (int j = 0; j < columns.length; j++) {
Column c = columns[j];
ExpressionColumn ec = new ExpressionColumn(session.getDatabase(), null, alias, c.getName());
expressions.add(i++, ec);
}
i--;
}
}
}
public void init() throws SQLException {
if (SysProperties.CHECK && checkInit) {
throw Message.getInternalError();
}
expandColumnList();
visibleColumnCount = expressions.size();
ObjectArray expressionSQL;
if (orderList != null || group != null) {
expressionSQL = new ObjectArray();
for (int i = 0; i < expressions.size(); i++) {
Expression expr = (Expression) expressions.get(i);
expr = expr.getNonAliasExpression();
String sql = expr.getSQL();
expressionSQL.add(sql);
}
} else {
expressionSQL = null;
}
if (orderList != null) {
initOrder(expressions, expressionSQL, orderList, visibleColumnCount, distinct);
}
distinctColumnCount = expressions.size();
if (having != null) {
expressions.add(having);
havingIndex = expressions.size() - 1;
having = null;
} else {
havingIndex = -1;
}
// first visible columns, then order by, then having,
// and group by at the end
if (group != null) {
groupIndex = new int[group.size()];
for (int i = 0; i < group.size(); i++) {
Expression expr = (Expression) group.get(i);
String sql = expr.getSQL();
int found = -1;
for (int j = 0; j < expressionSQL.size(); j++) {
String s2 = (String) expressionSQL.get(j);
if (s2.equals(sql)) {
found = j;
break;
}
}
if (found < 0) {
int index = expressions.size();
groupIndex[i] = index;
expressions.add(expr);
} else {
groupIndex[i] = found;
}
}
groupByExpression = new boolean[expressions.size()];
for (int i = 0; i < groupIndex.length; i++) {
groupByExpression[groupIndex[i]] = true;
}
group = null;
}
// map columns in select list and condition
for (int i = 0; i < filters.size(); i++) {
TableFilter f = (TableFilter) filters.get(i);
for (int j = 0; j < expressions.size(); j++) {
Expression expr = (Expression) expressions.get(j);
expr.mapColumns(f, 0);
}
if (condition != null) {
condition.mapColumns(f, 0);
}
}
checkInit = true;
}
public void prepare() throws SQLException {
if (isPrepared) {
// sometimes a subquery is prepared twice (CREATE TABLE AS SELECT)
return;
}
if (SysProperties.CHECK && !checkInit) {
throw Message.getInternalError("not initialized");
}
if (orderList != null) {
sort = prepareOrder(orderList, expressions.size());
orderList = null;
}
for (int i = 0; i < expressions.size(); i++) {
Expression e = (Expression) expressions.get(i);
expressions.set(i, e.optimize(session));
}
if (condition != null) {
condition = condition.optimize(session);
if (SysProperties.OPTIMIZE_IN_JOIN) {
condition = condition.optimizeInJoin(session, this);
}
for (int j = 0; j < filters.size(); j++) {
TableFilter f = (TableFilter) filters.get(j);
condition.createIndexConditions(session, f);
}
}
if (isGroupQuery && groupIndex == null && havingIndex < 0 && filters.size() == 1) {
if (condition == null) {
ExpressionVisitor optimizable = ExpressionVisitor.get(ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL);
optimizable.table = ((TableFilter) filters.get(0)).getTable();
isQuickQuery = isEverything(optimizable);
}
}
cost = preparePlan();
if (SysProperties.OPTIMIZE_DISTINCT && distinct && !isGroupQuery && filters.size() == 1 && expressions.size() == 1 && condition == null) {
Expression expr = (Expression) expressions.get(0);
expr = expr.getNonAliasExpression();
if (expr instanceof ExpressionColumn) {
Column column = ((ExpressionColumn) expr).getColumn();
int selectivity = column.getSelectivity();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?