提交 387316e1 authored 作者: Thomas Mueller's avatar Thomas Mueller

ROWNUM could not be used for pagination. The follow query returned no rows:…

ROWNUM could not be used for pagination. The follow query returned no rows: select x from (select *, rownum as r from system_range(1, 3)) where r=2;
上级 2011d637
...@@ -997,9 +997,15 @@ public class Select extends Query { ...@@ -997,9 +997,15 @@ public class Select extends Query {
public void addGlobalCondition(Parameter param, int columnId, int comparisonType) { public void addGlobalCondition(Parameter param, int columnId, int comparisonType) {
addParameter(param); addParameter(param);
Expression comp;
Expression col = expressions.get(columnId); Expression col = expressions.get(columnId);
col = col.getNonAliasExpression(); col = col.getNonAliasExpression();
Expression comp = new Comparison(session, comparisonType, col, param); if (col.isEverything(ExpressionVisitor.QUERY_COMPARABLE)) {
comp = new Comparison(session, comparisonType, col, param);
} else {
// add the parameters, so they can be set later
comp = new Comparison(session, Comparison.EQUAL, param, param);
}
comp = comp.optimize(session); comp = comp.optimize(session);
boolean addToCondition = true; boolean addToCondition = true;
if (isGroupQuery) { if (isGroupQuery) {
......
...@@ -236,6 +236,7 @@ public class ExpressionColumn extends Expression { ...@@ -236,6 +236,7 @@ public class ExpressionColumn extends Expression {
return false; return false;
case ExpressionVisitor.READONLY: case ExpressionVisitor.READONLY:
case ExpressionVisitor.DETERMINISTIC: case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.QUERY_COMPARABLE:
return true; return true;
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
return this.queryLevel < visitor.getQueryLevel(); return this.queryLevel < visitor.getQueryLevel();
......
...@@ -63,6 +63,14 @@ public class ExpressionVisitor { ...@@ -63,6 +63,14 @@ public class ExpressionVisitor {
*/ */
public static final int GET_DEPENDENCIES = 7; public static final int GET_DEPENDENCIES = 7;
/**
* Can the expression be added to a condition of an outer query.
* Example: ROWNUM() can't be added as a condition to the inner query of
* select id from (select t.*, rownum as r from test t) where r between 2 and 3;
* Also a sequence expression must not be used.
*/
public static final int QUERY_COMPARABLE = 8;
private int queryLevel; private int queryLevel;
private Table table; private Table table;
private int type; private int type;
......
...@@ -82,13 +82,12 @@ public class JavaAggregate extends Expression { ...@@ -82,13 +82,12 @@ public class JavaAggregate extends Expression {
case ExpressionVisitor.DETERMINISTIC: case ExpressionVisitor.DETERMINISTIC:
// TODO optimization: some functions are deterministic, but we don't // TODO optimization: some functions are deterministic, but we don't
// know (no setting for that) // know (no setting for that)
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
// user defined aggregate functions can not be optimized
return false; return false;
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
visitor.addDependency(userAggregate); visitor.addDependency(userAggregate);
break; break;
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
// user defined aggregate functions can not be optimized
return false;
default: default:
} }
for (Expression e : args) { for (Expression e : args) {
......
...@@ -126,23 +126,19 @@ public class Parameter extends Expression implements ParameterInterface { ...@@ -126,23 +126,19 @@ public class Parameter extends Expression implements ParameterInterface {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) { switch(visitor.getType()) {
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
return true;
case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY:
return true;
case ExpressionVisitor.INDEPENDENT:
return value != null;
case ExpressionVisitor.EVALUATABLE: case ExpressionVisitor.EVALUATABLE:
// the parameter _will_be_ evaluatable at execute time // the parameter _will_be_ evaluatable at execute time
return true;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
// it is checked independently if the value is the same as the last time // it is checked independently if the value is the same as the last time
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER: case ExpressionVisitor.NOT_FROM_RESOLVER:
return true; case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY:
return true; return true;
case ExpressionVisitor.INDEPENDENT:
return value != null;
default: default:
throw DbException.throwInternalError("type="+visitor.getType()); throw DbException.throwInternalError("type="+visitor.getType());
} }
......
...@@ -67,22 +67,17 @@ public class Rownum extends Expression { ...@@ -67,22 +67,17 @@ public class Rownum extends Expression {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) { switch(visitor.getType()) {
case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL: case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
return false;
case ExpressionVisitor.DETERMINISTIC: case ExpressionVisitor.DETERMINISTIC:
return false;
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
return false; return false;
case ExpressionVisitor.EVALUATABLE: case ExpressionVisitor.EVALUATABLE:
return true;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
// if everything else is the same, the rownum is the same
return true;
case ExpressionVisitor.READONLY: case ExpressionVisitor.READONLY:
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER: case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
// if everything else is the same, the rownum is the same
return true; return true;
default: default:
throw DbException.throwInternalError("type="+visitor.getType()); throw DbException.throwInternalError("type="+visitor.getType());
......
...@@ -70,20 +70,18 @@ public class SequenceValue extends Expression { ...@@ -70,20 +70,18 @@ public class SequenceValue extends Expression {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) { switch(visitor.getType()) {
case ExpressionVisitor.EVALUATABLE:
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL: case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true; return true;
case ExpressionVisitor.DETERMINISTIC: case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY: case ExpressionVisitor.READONLY:
return false;
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
case ExpressionVisitor.QUERY_COMPARABLE:
return false; return false;
case ExpressionVisitor.EVALUATABLE:
return true;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
visitor.addDataModificationId(sequence.getModificationId()); visitor.addDataModificationId(sequence.getModificationId());
return true; return true;
case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
visitor.addDependency(sequence); visitor.addDependency(sequence);
return true; return true;
......
...@@ -135,19 +135,14 @@ public class ValueExpression extends Expression { ...@@ -135,19 +135,14 @@ public class ValueExpression extends Expression {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch (visitor.getType()) { switch (visitor.getType()) {
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL: case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
return true;
case ExpressionVisitor.DETERMINISTIC: case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY: case ExpressionVisitor.READONLY:
return true;
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
return true;
case ExpressionVisitor.EVALUATABLE: case ExpressionVisitor.EVALUATABLE:
return true;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
return true;
case ExpressionVisitor.NOT_FROM_RESOLVER: case ExpressionVisitor.NOT_FROM_RESOLVER:
return true;
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.QUERY_COMPARABLE:
return true; return true;
default: default:
throw DbException.throwInternalError("type=" + visitor.getType()); throw DbException.throwInternalError("type=" + visitor.getType());
......
...@@ -57,24 +57,19 @@ public class Variable extends Expression { ...@@ -57,24 +57,19 @@ public class Variable extends Expression {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) { switch(visitor.getType()) {
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
return true;
case ExpressionVisitor.DETERMINISTIC:
return false;
case ExpressionVisitor.READONLY:
return true;
case ExpressionVisitor.INDEPENDENT:
return true;
case ExpressionVisitor.EVALUATABLE: case ExpressionVisitor.EVALUATABLE:
// the value will be evaluated at execute time // the value will be evaluated at execute time
return true;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
// it is checked independently if the value is the same as the last time // it is checked independently if the value is the same as the last time
return true; case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.READONLY:
case ExpressionVisitor.INDEPENDENT:
case ExpressionVisitor.NOT_FROM_RESOLVER: case ExpressionVisitor.NOT_FROM_RESOLVER:
return true; case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.GET_DEPENDENCIES: case ExpressionVisitor.GET_DEPENDENCIES:
return true; return true;
case ExpressionVisitor.DETERMINISTIC:
return false;
default: default:
throw DbException.throwInternalError("type="+visitor.getType()); throw DbException.throwInternalError("type="+visitor.getType());
} }
......
select x from (select *, rownum as r from system_range(1, 3)) where r=2;
> 2;
select cast(cast('01020304-0506-0708-090a-0b0c0d0e0f00' as uuid) as binary); select cast(cast('01020304-0506-0708-090a-0b0c0d0e0f00' as uuid) as binary);
> 0102030405060708090a0b0c0d0e0f00; > 0102030405060708090a0b0c0d0e0f00;
create table test(name varchar(255)) as select 'Hello+World+'; create table test(name varchar(255)) as select 'Hello+World+';
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论