QuerySpecification.java (hsqldb-2.6.0) | : | QuerySpecification.java (hsqldb-2.6.1) | ||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | */ | |||
package org.hsqldb; | package org.hsqldb; | |||
import java.util.Locale; | ||||
import org.hsqldb.HsqlNameManager.HsqlName; | import org.hsqldb.HsqlNameManager.HsqlName; | |||
import org.hsqldb.HsqlNameManager.SimpleName; | import org.hsqldb.HsqlNameManager.SimpleName; | |||
import org.hsqldb.ParserDQL.CompileContext; | import org.hsqldb.ParserDQL.CompileContext; | |||
import org.hsqldb.RangeVariable.RangeIteratorRight; | import org.hsqldb.RangeVariable.RangeIteratorRight; | |||
import org.hsqldb.error.Error; | import org.hsqldb.error.Error; | |||
import org.hsqldb.error.ErrorCode; | import org.hsqldb.error.ErrorCode; | |||
import org.hsqldb.index.Index; | import org.hsqldb.index.Index; | |||
import org.hsqldb.lib.ArrayListIdentity; | import org.hsqldb.lib.ArrayListIdentity; | |||
import org.hsqldb.lib.ArrayUtil; | import org.hsqldb.lib.ArrayUtil; | |||
import org.hsqldb.lib.HashSet; | import org.hsqldb.lib.HashSet; | |||
skipping to change at line 67 | skipping to change at line 69 | |||
import org.hsqldb.result.ResultMetaData; | import org.hsqldb.result.ResultMetaData; | |||
import org.hsqldb.result.ResultProperties; | import org.hsqldb.result.ResultProperties; | |||
import org.hsqldb.types.Type; | import org.hsqldb.types.Type; | |||
import org.hsqldb.types.Types; | import org.hsqldb.types.Types; | |||
/** | /** | |||
* Implementation of an SQL query specification, including SELECT. | * Implementation of an SQL query specification, including SELECT. | |||
* | * | |||
* @author Fred Toussi (fredt@users dot sourceforge.net) | * @author Fred Toussi (fredt@users dot sourceforge.net) | |||
* | * | |||
* @version 2.5.1 | * @version 2.6.1 | |||
* @since 1.9.0 | * @since 1.9.0 | |||
*/ | */ | |||
public class QuerySpecification extends QueryExpression { | public class QuerySpecification extends QueryExpression { | |||
// | // | |||
public int resultRangePosition; | public int resultRangePosition; | |||
public boolean isDistinctSelect; | public boolean isDistinctSelect; | |||
public boolean isAggregated; | public boolean isAggregated; | |||
public boolean isGrouped; | public boolean isGrouped; | |||
public boolean isGroupingSets; | public boolean isGroupingSets; | |||
skipping to change at line 748 | skipping to change at line 750 | |||
} | } | |||
private void resolveColumnReferencesAndAllocate(Session session, | private void resolveColumnReferencesAndAllocate(Session session, | |||
Expression expression, int count, RangeGroup[] rangeGroups, | Expression expression, int count, RangeGroup[] rangeGroups, | |||
boolean withSequences) { | boolean withSequences) { | |||
if (expression == null) { | if (expression == null) { | |||
return; | return; | |||
} | } | |||
List list = expression.resolveColumnReferences(session, this, | List list = expression.resolveColumnReferences(session, this, count, | |||
count, rangeGroups, null, withSequences); | rangeGroups, null, withSequences); | |||
if (list != null) { | if (list != null) { | |||
for (int i = 0; i < list.size(); i++) { | for (int i = 0; i < list.size(); i++) { | |||
Expression e = (Expression) list.get(i); | Expression e = (Expression) list.get(i); | |||
boolean resolved = true; | boolean resolved = true; | |||
if (e.isSelfAggregate()) { | if (e.isSelfAggregate()) { | |||
for (int j = 0; j < e.nodes.length; j++) { | for (int j = 0; j < e.nodes.length; j++) { | |||
List colList = e.nodes[j].resolveColumnReferences( | List colList = e.nodes[j].resolveColumnReferences( | |||
session, this, count, RangeGroup.emptyArray, null, | session, this, count, RangeGroup.emptyArray, null, | |||
skipping to change at line 994 | skipping to change at line 996 | |||
OrderedHashSet set) { | OrderedHashSet set) { | |||
for (int i = 0; i < indexStartAggregates; i++) { | for (int i = 0; i < indexStartAggregates; i++) { | |||
set = exprColumns[i].collectRangeVariables(rangeVars, set); | set = exprColumns[i].collectRangeVariables(rangeVars, set); | |||
} | } | |||
if (queryCondition != null) { | if (queryCondition != null) { | |||
set = queryCondition.collectRangeVariables(rangeVars, set); | set = queryCondition.collectRangeVariables(rangeVars, set); | |||
} | } | |||
for (int i = 0; i < rangeVariables.length; i++) { | ||||
set = rangeVariables[i].collectRangeVariables(rangeVars, set); | ||||
} | ||||
return set; | return set; | |||
} | } | |||
OrderedHashSet collectRangeVariables(OrderedHashSet set) { | OrderedHashSet collectRangeVariables(OrderedHashSet set) { | |||
for (int i = 0; i < indexStartAggregates; i++) { | for (int i = 0; i < indexStartAggregates; i++) { | |||
set = exprColumns[i].collectRangeVariables(set); | set = exprColumns[i].collectRangeVariables(set); | |||
} | } | |||
if (queryCondition != null) { | if (queryCondition != null) { | |||
skipping to change at line 1552 | skipping to change at line 1558 | |||
set = e.getUnkeyedColumns(set); | set = e.getUnkeyedColumns(set); | |||
} | } | |||
return set == null; | return set == null; | |||
} | } | |||
/** | /** | |||
* Returns the result of executing this Select. | * Returns the result of executing this Select. | |||
* | * | |||
* @param maxrows may be 0 to indicate no limit on the number of rows. | * @param maxRows may be 0 to indicate no limit on the number of rows. | |||
* Positive values limit the size of the result set. | * Positive values limit the size of the result set. | |||
* @return the result of executing this Select | * @return the result of executing this Select | |||
*/ | */ | |||
Result getResult(Session session, int maxrows) { | Result getResult(Session session, int maxRows) { | |||
//todo single row | RowSetNavigatorData navigator = new RowSetNavigatorData(session, this); | |||
Result r = getSingleResult(session, maxrows); | int[] limits = sortAndSlice.getLimits(session, this, maxRows); | |||
int skipCount = 0; | ||||
r.getNavigator().reset(); | int limitCount = limits[2]; | |||
return r; | if (sortAndSlice.skipFullResult) { | |||
} | skipCount = limits[0]; | |||
limitCount = limits[1]; | ||||
} | ||||
private Result getSingleResult(Session session, int maxRows) { | Result r = buildResult(session, navigator, skipCount, limitCount); | |||
int[] limits = sortAndSlice.getLimits(session, this, maxRows); | navigator = (RowSetNavigatorData) r.getNavigator(); | |||
Result r = buildResult(session, limits); | ||||
RowSetNavigatorData navigator = (RowSetNavigatorData) r.getNavigator(); | ||||
if (isDistinctSelect) { | if (isDistinctSelect) { | |||
navigator.removeDuplicates(); | navigator.removeDuplicates(); | |||
} | } | |||
if (sortAndSlice.hasOrder()) { | if (sortAndSlice.hasOrder() && !sortAndSlice.skipSort) { | |||
navigator.sortOrder(); | navigator.sortOrder(); | |||
} | } | |||
if (limits != SortAndSlice.defaultLimits | if (limits != SortAndSlice.defaultLimits | |||
&& !sortAndSlice.skipFullResult) { | && !sortAndSlice.skipFullResult) { | |||
navigator.trim(limits[0], limits[1]); | navigator.trim(limits[0], limits[1]); | |||
} | } | |||
r.getNavigator().reset(); | ||||
return r; | return r; | |||
} | } | |||
private Result buildResult(Session session, int[] limits) { | private Result buildResult(Session session, RowSetNavigatorData navigator, | |||
int skipCount, int limitCount) { | ||||
RowSetNavigatorData navigator = new RowSetNavigatorData(session, this); | Result result = Result.newResult(navigator); | |||
Result result = Result.newResult(navigator); | boolean isResultGrouped = isGrouped && !isSimpleDistinct; | |||
boolean resultGrouped = isGrouped && !isSimpleDistinct; | ||||
result.metaData = resultMetaData; | result.metaData = resultMetaData; | |||
if (isUpdatable) { | if (isUpdatable) { | |||
result.rsProperties = ResultProperties.updatablePropsValue; | result.rsProperties = ResultProperties.updatablePropsValue; | |||
} | } | |||
int skipCount = 0; | if (isSimpleCount) { | |||
int limitCount = limits[2]; | getSimpleCountResult(session, navigator); | |||
if (sortAndSlice.skipFullResult) { | return result; | |||
skipCount = limits[0]; | ||||
limitCount = limits[1]; | ||||
} | } | |||
if (this.isSimpleCount) { | if (limitCount == 0) { | |||
Object[] data = new Object[indexLimitData]; | ||||
Table table = rangeVariables[0].getTable(); | ||||
table.materialise(session); | ||||
PersistentStore store = table.getRowStore(session); | ||||
long count = store.elementCount(session); | ||||
data[indexStartAggregates] = ValuePool.getLong(count); | ||||
navigator.add(data); | ||||
navigator.reset(); | ||||
session.sessionContext.setRangeIterator(navigator); | ||||
if (navigator.next()) { | ||||
data = navigator.getCurrent(); | ||||
for (int i = 0; i < indexStartAggregates; i++) { | ||||
data[i] = exprColumns[i].getValue(session); | ||||
} | ||||
} | ||||
session.sessionContext.unsetRangeIterator(navigator); | ||||
return result; | return result; | |||
} | } | |||
if (isGroupingSets) { | ||||
session.sessionContext.setGroup(null); | ||||
} | ||||
int memoryRowLimit = | ||||
(!isAggregated && !isSingleMemoryTable && !isGroupingSets) | ||||
? session.resultMaxMemoryRows | ||||
: 0; | ||||
int fullJoinIndex = 0; | int fullJoinIndex = 0; | |||
RangeIterator[] rangeIterators = | RangeIterator[] rangeIterators = | |||
new RangeIterator[rangeVariables.length]; | new RangeIterator[rangeVariables.length]; | |||
for (int i = 0; i < rangeVariables.length; i++) { | for (int i = 0; i < rangeVariables.length; i++) { | |||
rangeIterators[i] = rangeVariables[i].getIterator(session); | rangeIterators[i] = rangeVariables[i].getIterator(session); | |||
} | } | |||
session.sessionContext.rownum = 1; | session.sessionContext.rownum = 1; | |||
skipping to change at line 1688 | skipping to change at line 1678 | |||
continue; | continue; | |||
} | } | |||
} else { | } else { | |||
it.reset(); | it.reset(); | |||
currentIndex--; | currentIndex--; | |||
continue; | continue; | |||
} | } | |||
if (limitCount == 0) { | ||||
break; | ||||
} | ||||
session.sessionData.startRowProcessing(); | session.sessionData.startRowProcessing(); | |||
Object[] data = new Object[indexLimitData]; | Object[] data = new Object[indexLimitData]; | |||
int start = 0; | int start = 0; | |||
if (isGroupingSets) { | if (isGroupingSets) { | |||
start = indexLimitVisible; | start = indexLimitVisible; | |||
} | } | |||
for (int i = start; i < indexStartAggregates; i++) { | for (int i = start; i < indexStartAggregates; i++) { | |||
skipping to change at line 1730 | skipping to change at line 1716 | |||
session.sessionContext.rownum++; | session.sessionContext.rownum++; | |||
if (skipCount > 0) { | if (skipCount > 0) { | |||
skipCount--; | skipCount--; | |||
continue; | continue; | |||
} | } | |||
Object[] groupData = null; | Object[] groupData = null; | |||
if (isAggregated || resultGrouped) { | if (isAggregated || isResultGrouped) { | |||
groupData = navigator.getGroupData(data); | groupData = navigator.getGroupData(data); | |||
if (groupData != null) { | if (groupData != null) { | |||
data = groupData; | data = groupData; | |||
} | } | |||
} | } | |||
for (int i = indexStartAggregates; i < indexLimitExpressions; | for (int i = indexStartAggregates; i < indexLimitExpressions; | |||
i++) { | i++) { | |||
data[i] = exprColumns[i].updateAggregatingValue(session, | data[i] = exprColumns[i].updateAggregatingValue(session, | |||
skipping to change at line 1760 | skipping to change at line 1746 | |||
} | } | |||
currentIndex = 0; | currentIndex = 0; | |||
} | } | |||
} else if (isAggregated) { | } else if (isAggregated) { | |||
navigator.update(groupData, data); | navigator.update(groupData, data); | |||
} | } | |||
int rowCount = navigator.getSize(); | int rowCount = navigator.getSize(); | |||
if (rowCount == session.resultMaxMemoryRows && !isAggregated | if (rowCount == memoryRowLimit) { | |||
&& !isSingleMemoryTable && !isGroupingSets) { | ||||
navigator = new RowSetNavigatorDataTable(session, this, | navigator = new RowSetNavigatorDataTable(session, this, | |||
navigator); | navigator); | |||
result.setNavigator(navigator); | result.setNavigator(navigator); | |||
memoryRowLimit = 0; | ||||
} | } | |||
if (isAggregated || resultGrouped) { | if (isAggregated || isResultGrouped) { | |||
if (!sortAndSlice.isGenerated) { | if (!sortAndSlice.isGenerated) { | |||
continue; | continue; | |||
} | } | |||
} | } | |||
if (rowCount >= limitCount) { | if (rowCount >= limitCount) { | |||
break; | break; | |||
} | } | |||
} | } | |||
skipping to change at line 1889 | skipping to change at line 1876 | |||
} | } | |||
navigator.update(groupData, data); | navigator.update(groupData, data); | |||
} | } | |||
} | } | |||
} | } | |||
navigator.reset(); | navigator.reset(); | |||
if (isAggregated) { | if (isAggregated) { | |||
if (!resultGrouped && navigator.getSize() == 0) { | if (!isResultGrouped && navigator.getSize() == 0) { | |||
Object[] data = new Object[exprColumns.length]; | Object[] data = new Object[exprColumns.length]; | |||
for (int i = 0; i < indexStartAggregates; i++) { | for (int i = 0; i < indexStartAggregates; i++) { | |||
if (!aggregateCheck[i]) { | if (!aggregateCheck[i]) { | |||
data[i] = exprColumns[i].getValue(session); | data[i] = exprColumns[i].getValue(session); | |||
} | } | |||
} | } | |||
navigator.add(data); | navigator.add(data); | |||
} | } | |||
skipping to change at line 1945 | skipping to change at line 1932 | |||
} | } | |||
navigator.reset(); | navigator.reset(); | |||
} | } | |||
session.sessionContext.unsetRangeIterator(navigator); | session.sessionContext.unsetRangeIterator(navigator); | |||
return result; | return result; | |||
} | } | |||
private void getSimpleCountResult(Session session, | ||||
RowSetNavigatorData navigator) { | ||||
Object[] data = new Object[indexLimitData]; | ||||
Table table = rangeVariables[0].getTable(); | ||||
table.materialise(session); | ||||
PersistentStore store = table.getRowStore(session); | ||||
long count = store.elementCount(session); | ||||
data[indexStartAggregates] = ValuePool.getLong(count); | ||||
navigator.add(data); | ||||
navigator.reset(); | ||||
session.sessionContext.setRangeIterator(navigator); | ||||
if (navigator.next()) { | ||||
data = navigator.getCurrent(); | ||||
for (int i = 0; i < indexStartAggregates; i++) { | ||||
data[i] = exprColumns[i].getValue(session); | ||||
} | ||||
} | ||||
session.sessionContext.unsetRangeIterator(navigator); | ||||
} | ||||
void setReferenceableColumns() { | void setReferenceableColumns() { | |||
accessibleColumns = new boolean[indexLimitVisible]; | accessibleColumns = new boolean[indexLimitVisible]; | |||
IntValueHashMap aliases = new IntValueHashMap(); | IntValueHashMap aliases = new IntValueHashMap(); | |||
for (int i = 0; i < indexLimitVisible; i++) { | for (int i = 0; i < indexLimitVisible; i++) { | |||
Expression expression = exprColumns[i]; | Expression expression = exprColumns[i]; | |||
String alias = expression.getAlias(); | String alias = expression.getAlias(); | |||
skipping to change at line 2002 | skipping to change at line 2017 | |||
Expression e = exprColumns[i]; | Expression e = exprColumns[i]; | |||
ColumnSchema tableColumn = null; | ColumnSchema tableColumn = null; | |||
ColumnBase column; | ColumnBase column; | |||
tableColumn = e.getColumn(); | tableColumn = e.getColumn(); | |||
resultMetaData.columnTypes[i] = e.getDataType(); | resultMetaData.columnTypes[i] = e.getDataType(); | |||
if (tableColumn == null) { | if (tableColumn == null) { | |||
column = new ColumnBase(); | column = new ColumnBase(); | |||
} else { | } else { | |||
column = new ColumnBase(session.database.getCatalogName().name, | column = new ColumnBase(session.database.getCatalogName(), | |||
tableColumn); | tableColumn, | |||
lowerCaseResultIdentifier); | ||||
} | } | |||
column.setType(e.getDataType()); | column.setType(e.getDataType()); | |||
SimpleName alias = e.getSimpleName(); | ||||
String colLabel = alias == null ? "" | ||||
: alias.name; | ||||
if (lowerCaseResultIdentifier) { | ||||
if (!alias.isNameQuoted) { | ||||
colLabel = colLabel.toLowerCase(Locale.ENGLISH); | ||||
} | ||||
} | ||||
resultMetaData.columns[i] = column; | resultMetaData.columns[i] = column; | |||
resultMetaData.columnLabels[i] = e.getAlias(); | resultMetaData.columnLabels[i] = colLabel; | |||
} | } | |||
} | } | |||
private void setResultNullability() { | private void setResultNullability() { | |||
for (int i = 0; i < indexLimitVisible; i++) { | for (int i = 0; i < indexLimitVisible; i++) { | |||
Expression e = exprColumns[i]; | Expression e = exprColumns[i]; | |||
byte nullability = e.getNullability(); | byte nullability = e.getNullability(); | |||
if (e.opType == OpTypes.COLUMN) { | if (e.opType == OpTypes.COLUMN) { | |||
End of changes. 28 change blocks. | ||||
62 lines changed or deleted | 88 lines changed or added |