提交 73af7108 authored 作者: Thomas Mueller's avatar Thomas Mueller

Count on a column that can not be null is now optimized to COUNT(*).

上级 205a3901
...@@ -264,6 +264,7 @@ public class Aggregate extends Expression { ...@@ -264,6 +264,7 @@ public class Aggregate extends Expression {
public Value getValue(Session session) { public Value getValue(Session session) {
if (select.isQuickAggregateQuery()) { if (select.isQuickAggregateQuery()) {
switch (type) { switch (type) {
case COUNT:
case COUNT_ALL: case COUNT_ALL:
Table table = select.getTopTableFilter().getTable(); Table table = select.getTopTableFilter().getTable();
return ValueLong.get(table.getRowCount(session)); return ValueLong.get(table.getRowCount(session));
...@@ -546,6 +547,8 @@ public class Aggregate extends Expression { ...@@ -546,6 +547,8 @@ public class Aggregate extends Expression {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
if (visitor.getType() == ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL) { if (visitor.getType() == ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL) {
switch (type) { switch (type) {
case COUNT:
return on.getNullable() == Column.NOT_NULLABLE && visitor.getTable().canGetRowCount();
case COUNT_ALL: case COUNT_ALL:
return visitor.getTable().canGetRowCount(); return visitor.getTable().canGetRowCount();
case MIN: case MIN:
......
...@@ -51,6 +51,7 @@ import org.h2.test.db.TestRunscript; ...@@ -51,6 +51,7 @@ import org.h2.test.db.TestRunscript;
import org.h2.test.db.TestSQLInjection; import org.h2.test.db.TestSQLInjection;
import org.h2.test.db.TestScript; import org.h2.test.db.TestScript;
import org.h2.test.db.TestScriptSimple; import org.h2.test.db.TestScriptSimple;
import org.h2.test.db.TestSelectCountNonNullColumn;
import org.h2.test.db.TestSequence; import org.h2.test.db.TestSequence;
import org.h2.test.db.TestSessionsLocks; import org.h2.test.db.TestSessionsLocks;
import org.h2.test.db.TestSpaceReuse; import org.h2.test.db.TestSpaceReuse;
...@@ -575,6 +576,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -575,6 +576,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new TestRunscript().runTest(this); new TestRunscript().runTest(this);
new TestSQLInjection().runTest(this); new TestSQLInjection().runTest(this);
new TestSessionsLocks().runTest(this); new TestSessionsLocks().runTest(this);
new TestSelectCountNonNullColumn().runTest(this);
new TestSequence().runTest(this); new TestSequence().runTest(this);
new TestSpaceReuse().runTest(this); new TestSpaceReuse().runTest(this);
new TestSpeed().runTest(this); new TestSpeed().runTest(this);
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
/**
* Test that count(column) is converted to count(*) if the column is not nullable.
*/
public class TestSelectCountNonNullColumn extends TestBase {
private static final String DBNAME = "selectCountNonNullColumn";
private Statement stat;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws SQLException {
deleteDb(DBNAME);
Connection conn = getConnection(DBNAME);
stat = conn.createStatement();
stat.execute("CREATE TABLE SIMPLE(KEY VARCHAR(25) PRIMARY KEY, NAME VARCHAR(25))");
stat.execute("INSERT INTO SIMPLE(KEY) VALUES('k1')");
stat.execute("INSERT INTO SIMPLE(KEY,NAME) VALUES('k2','name2')");
checkKeyCount(-1);
checkNameCount(-1);
checkStarCount(-1);
checkKeyCount(2);
checkNameCount(1);
checkStarCount(2);
conn.close();
}
void checkStarCount(long expect) throws SQLException {
String sql = "SELECT COUNT(*) FROM SIMPLE";
if (expect < 0) {
sql = "EXPLAIN " + sql;
}
ResultSet rs = stat.executeQuery(sql);
rs.next();
if (expect >= 0) {
assertEquals(expect, rs.getLong(1));
} else {
// System.out.println(rs.getString(1));
assertEquals("SELECT\n" + " COUNT(*)\n" + "FROM PUBLIC.SIMPLE\n" + " /* PUBLIC.SIMPLE.tableScan */\n"
+ "/* direct lookup */", rs.getString(1));
}
}
void checkKeyCount(long expect) throws SQLException {
String sql = "SELECT COUNT(KEY) FROM SIMPLE";
if (expect < 0) {
sql = "EXPLAIN " + sql;
}
ResultSet rs = stat.executeQuery(sql);
rs.next();
if (expect >= 0) {
assertEquals(expect, rs.getLong(1));
} else {
// System.out.println(rs.getString(1));
assertEquals("SELECT\n" + " COUNT(KEY)\n" + "FROM PUBLIC.SIMPLE\n"
+ " /* PUBLIC.SIMPLE.tableScan */\n" + "/* direct lookup */", rs.getString(1));
}
}
void checkNameCount(long expect) throws SQLException {
String sql = "SELECT COUNT(NAME) FROM SIMPLE";
if (expect < 0) {
sql = "EXPLAIN " + sql;
}
ResultSet rs = stat.executeQuery(sql);
rs.next();
if (expect >= 0) {
assertEquals(expect, rs.getLong(1));
} else {
// System.out.println(rs.getString(1));
assertEquals("SELECT\n" + " COUNT(NAME)\n" + "FROM PUBLIC.SIMPLE\n"
+ " /* PUBLIC.SIMPLE.tableScan */", rs.getString(1));
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论