提交 1e9b6d64 authored 作者: S.Vladykin's avatar S.Vladykin

Merge branch 'viewindex' into batchview2

...@@ -31,7 +31,7 @@ public class AlterView extends DefineCommand { ...@@ -31,7 +31,7 @@ public class AlterView extends DefineCommand {
public int update() { public int update() {
session.commit(true); session.commit(true);
session.getUser().checkRight(view, Right.ALL); session.getUser().checkRight(view, Right.ALL);
DbException e = view.recompile(session, false); DbException e = view.recompile(session, false, true);
if (e != null) { if (e != null) {
throw e; throw e;
} }
......
...@@ -811,7 +811,7 @@ public class Database implements DataHandler { ...@@ -811,7 +811,7 @@ public class Database implements DataHandler {
if (obj instanceof TableView) { if (obj instanceof TableView) {
TableView view = (TableView) obj; TableView view = (TableView) obj;
if (view.isInvalid()) { if (view.isInvalid()) {
view.recompile(session, true); view.recompile(session, true, false);
if (!view.isInvalid()) { if (!view.isInvalid()) {
recompileSuccessful = true; recompileSuccessful = true;
} }
...@@ -819,17 +819,7 @@ public class Database implements DataHandler { ...@@ -819,17 +819,7 @@ public class Database implements DataHandler {
} }
} }
} while (recompileSuccessful); } while (recompileSuccessful);
// when opening a database, views are initialized before indexes, TableView.clearIndexCaches(session.getDatabase());
// so they may not have the optimal plan yet
// this is not a problem, it is just nice to see the newest plan
for (Table obj : getAllTablesAndViews(false)) {
if (obj instanceof TableView) {
TableView view = (TableView) obj;
if (!view.isInvalid()) {
view.recompile(systemSession, true);
}
}
}
} }
private void initMetaTables() { private void initMetaTables() {
......
...@@ -482,7 +482,12 @@ public class Session extends SessionWithState { ...@@ -482,7 +482,12 @@ public class Session extends SessionWithState {
} }
} }
Parser parser = new Parser(this); Parser parser = new Parser(this);
try {
command = parser.prepareCommand(sql); command = parser.prepareCommand(sql);
} finally {
// we can't reuse sub-query indexes, so just drop the whole cache
subQueryIndexCache = null;
}
if (queryCache != null) { if (queryCache != null) {
if (command.isCacheable()) { if (command.isCacheable()) {
queryCache.put(sql, command); queryCache.put(sql, command);
...@@ -1319,8 +1324,8 @@ public class Session extends SessionWithState { ...@@ -1319,8 +1324,8 @@ public class Session extends SessionWithState {
public Map<Object, ViewIndex> getViewIndexCache(boolean subQuery) { public Map<Object, ViewIndex> getViewIndexCache(boolean subQuery) {
if (subQuery) { if (subQuery) {
// for sub-queries we don't need to use LRU because it should not grow too large // for sub-queries we don't need to use LRU because the cache should not
// for a single query and by the end of the statement we will drop the whole cache // grow too large for a single query (we drop the whole cache in the end of prepareLocal)
if (subQueryIndexCache == null) { if (subQueryIndexCache == null) {
subQueryIndexCache = New.hashMap(); subQueryIndexCache = New.hashMap();
} }
...@@ -1510,7 +1515,6 @@ public class Session extends SessionWithState { ...@@ -1510,7 +1515,6 @@ public class Session extends SessionWithState {
*/ */
public void endStatement() { public void endStatement() {
startStatement = -1; startStatement = -1;
subQueryIndexCache = null;
closeTemporaryResults(); closeTemporaryResults();
} }
......
...@@ -13,6 +13,7 @@ import org.h2.api.ErrorCode; ...@@ -13,6 +13,7 @@ import org.h2.api.ErrorCode;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.engine.User; import org.h2.engine.User;
...@@ -80,10 +81,10 @@ public class TableView extends Table { ...@@ -80,10 +81,10 @@ public class TableView extends Table {
String[] oldColumnNames = this.columnNames; String[] oldColumnNames = this.columnNames;
boolean oldRecursive = this.recursive; boolean oldRecursive = this.recursive;
init(querySQL, null, columnNames, session, recursive); init(querySQL, null, columnNames, session, recursive);
DbException e = recompile(session, force); DbException e = recompile(session, force, true);
if (e != null) { if (e != null) {
init(oldQuerySQL, null, oldColumnNames, session, oldRecursive); init(oldQuerySQL, null, oldColumnNames, session, oldRecursive);
recompile(session, true); recompile(session, true, false);
throw e; throw e;
} }
} }
...@@ -116,10 +117,11 @@ public class TableView extends Table { ...@@ -116,10 +117,11 @@ public class TableView extends Table {
* *
* @param session the session * @param session the session
* @param force if exceptions should be ignored * @param force if exceptions should be ignored
* @param clearIndexCache if we need to clear view index cache
* @return the exception if re-compiling this or any dependent view failed * @return the exception if re-compiling this or any dependent view failed
* (only when force is disabled) * (only when force is disabled)
*/ */
public synchronized DbException recompile(Session session, boolean force) { public synchronized DbException recompile(Session session, boolean force, boolean clearIndexCache) {
try { try {
compileViewQuery(session, querySQL); compileViewQuery(session, querySQL);
} catch (DbException e) { } catch (DbException e) {
...@@ -134,12 +136,15 @@ public class TableView extends Table { ...@@ -134,12 +136,15 @@ public class TableView extends Table {
initColumnsAndTables(session); initColumnsAndTables(session);
if (views != null) { if (views != null) {
for (TableView v : views) { for (TableView v : views) {
DbException e = v.recompile(session, force); DbException e = v.recompile(session, force, false);
if (e != null && !force) { if (e != null && !force) {
return e; return e;
} }
} }
} }
if (clearIndexCache) {
clearIndexCaches(database);
}
return force ? null : createException; return force ? null : createException;
} }
...@@ -399,10 +404,14 @@ public class TableView extends Table { ...@@ -399,10 +404,14 @@ public class TableView extends Table {
database.removeMeta(session, getId()); database.removeMeta(session, getId());
querySQL = null; querySQL = null;
index = null; index = null;
clearIndexCaches(database);
invalidate();
}
public static void clearIndexCaches(Database database) {
for (Session s : database.getSessions(true)) { for (Session s : database.getSessions(true)) {
s.clearViewIndexCache(); s.clearViewIndexCache();
} }
invalidate();
} }
@Override @Override
......
...@@ -45,7 +45,7 @@ public class TestAnnotationProcessor extends AbstractProcessor { ...@@ -45,7 +45,7 @@ public class TestAnnotationProcessor extends AbstractProcessor {
} }
public SourceVersion getSupportedSourceVersion() { public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_6; return SourceVersion.latest();
} }
@Override @Override
......
...@@ -1782,49 +1782,6 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1782,49 +1782,6 @@ public class TestFunctions extends TestBase implements AggregateFunction {
} }
private void testAnnotationProcessorsOutput() throws SQLException { private void testAnnotationProcessorsOutput() throws SQLException {
testAnnotationProcessorsOutput_emptyKey();
testAnnotationProcessorsOutput_invalidKey();
testAnnotationProcessorsOutput_oneInvalidKey();
testAnnotationProcessorsOutput_warnAndError();
}
private void testAnnotationProcessorsOutput_emptyKey() throws SQLException {
try {
System.setProperty(TestAnnotationProcessor.MESSAGES_KEY, "");
callCompiledFunction("test_atp_empty_key");
} finally {
System.clearProperty(TestAnnotationProcessor.MESSAGES_KEY);
}
}
private void testAnnotationProcessorsOutput_invalidKey() throws SQLException {
try {
System.setProperty(TestAnnotationProcessor.MESSAGES_KEY, "invalid");
callCompiledFunction("test_atp_invalid_key");
fail();
} catch (JdbcSQLException e) {
assertEquals(ErrorCode.SYNTAX_ERROR_1, e.getErrorCode());
assertContains(e.getMessage(), "'invalid'");
} finally {
System.clearProperty(TestAnnotationProcessor.MESSAGES_KEY);
}
}
private void testAnnotationProcessorsOutput_oneInvalidKey() throws SQLException {
try {
System.setProperty(TestAnnotationProcessor.MESSAGES_KEY, "invalid,foo");
callCompiledFunction("test_atp_one_invalid_key");
fail();
} catch (JdbcSQLException e) {
assertEquals(ErrorCode.SYNTAX_ERROR_1, e.getErrorCode());
assertContains(e.getMessage(), "enum");
assertContains(e.getMessage(), "Kind.invalid");
} finally {
System.clearProperty(TestAnnotationProcessor.MESSAGES_KEY);
}
}
private void testAnnotationProcessorsOutput_warnAndError() throws SQLException {
try { try {
System.setProperty(TestAnnotationProcessor.MESSAGES_KEY, "WARNING,foo1|ERROR,foo2"); System.setProperty(TestAnnotationProcessor.MESSAGES_KEY, "WARNING,foo1|ERROR,foo2");
callCompiledFunction("test_atp_warn_and_error"); callCompiledFunction("test_atp_warn_and_error");
......
...@@ -10,8 +10,9 @@ import java.sql.PreparedStatement; ...@@ -10,8 +10,9 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Session;
import org.h2.jdbc.JdbcConnection;
import org.h2.test.TestBase; import org.h2.test.TestBase;
/** /**
...@@ -33,7 +34,7 @@ public class TestView extends TestBase { ...@@ -33,7 +34,7 @@ public class TestView extends TestBase {
@Override @Override
public void test() throws SQLException { public void test() throws SQLException {
deleteDb("view"); deleteDb("view");
testSubQueryViewIndexCache();
testInnerSelectWithRownum(); testInnerSelectWithRownum();
testInnerSelectWithRange(); testInnerSelectWithRange();
testEmptyColumn(); testEmptyColumn();
...@@ -51,6 +52,53 @@ public class TestView extends TestBase { ...@@ -51,6 +52,53 @@ public class TestView extends TestBase {
deleteDb("view"); deleteDb("view");
} }
public void testSubQueryViewIndexCache() throws SQLException {
if (config.networked) {
return;
}
Connection conn = getConnection("view");
Statement stat = conn.createStatement();
stat.execute("drop table test if exists");
stat.execute("create table test(id int primary key, name varchar(25) unique, age int unique)");
// check that initial cache size is empty
Session s = (Session) ((JdbcConnection) conn).getSession();
s.clearViewIndexCache();
assertTrue(s.getViewIndexCache(true).isEmpty());
assertTrue(s.getViewIndexCache(false).isEmpty());
// create view command should not affect caches
stat.execute("create view v as select * from test");
assertTrue(s.getViewIndexCache(true).isEmpty());
assertTrue(s.getViewIndexCache(false).isEmpty());
// check view index cache
stat.executeQuery("select * from v where id > 0").next();
int size1 = s.getViewIndexCache(false).size();
assertTrue(size1 > 0);
assertTrue(s.getViewIndexCache(true).isEmpty());
stat.executeQuery("select * from v where name = 'xyz'").next();
int size2 = s.getViewIndexCache(false).size();
assertTrue(size2 > size1);
assertTrue(s.getViewIndexCache(true).isEmpty());
// check we did not add anything to view cache if we run a sub-query
stat.executeQuery("select * from (select * from test) where age = 17").next();
int size3 = s.getViewIndexCache(false).size();
assertEquals(size2, size3);
assertTrue(s.getViewIndexCache(true).isEmpty());
// check clear works
s.clearViewIndexCache();
assertTrue(s.getViewIndexCache(false).isEmpty());
assertTrue(s.getViewIndexCache(true).isEmpty());
// drop everything
stat.execute("drop view v");
stat.execute("drop table test");
conn.close();
}
private void testInnerSelectWithRownum() throws SQLException { private void testInnerSelectWithRownum() throws SQLException {
Connection conn = getConnection("view"); Connection conn = getConnection("view");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -14,7 +14,6 @@ import java.net.Socket; ...@@ -14,7 +14,6 @@ import java.net.Socket;
import java.util.HashMap; import java.util.HashMap;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.h2.build.code.SwitchSource; import org.h2.build.code.SwitchSource;
import org.h2.build.doc.XMLParser; import org.h2.build.doc.XMLParser;
...@@ -401,6 +400,23 @@ public class Build extends BuildBase { ...@@ -401,6 +400,23 @@ public class Build extends BuildBase {
writeFile(new File(fileName), checksums.getBytes()); writeFile(new File(fileName), checksums.getBytes());
} }
private static String canonicalPath(File file) {
try {
return file.getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private FileList excludeTestMetaInfFiles(FileList files) {
FileList testMetaInfFiles = files("src/test/META-INF");
int basePathLength = canonicalPath(new File("src/test")).length();
for (File file : testMetaInfFiles) {
files = files.exclude(canonicalPath(file).substring(basePathLength + 1));
}
return files;
}
/** /**
* Create the regular h2.jar file. * Create the regular h2.jar file.
*/ */
...@@ -424,6 +440,7 @@ public class Build extends BuildBase { ...@@ -424,6 +440,7 @@ public class Build extends BuildBase {
exclude("*.sh"). exclude("*.sh").
exclude("*.txt"). exclude("*.txt").
exclude("*.DS_Store"); exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
jar("bin/h2" + getJarSuffix(), files, "temp"); jar("bin/h2" + getJarSuffix(), files, "temp");
filter("src/installer/h2.sh", "bin/h2.sh", "h2.jar", "h2" + getJarSuffix()); filter("src/installer/h2.sh", "bin/h2.sh", "h2.jar", "h2" + getJarSuffix());
filter("src/installer/h2.bat", "bin/h2.bat", "h2.jar", "h2" + getJarSuffix()); filter("src/installer/h2.bat", "bin/h2.bat", "h2.jar", "h2" + getJarSuffix());
...@@ -455,6 +472,7 @@ public class Build extends BuildBase { ...@@ -455,6 +472,7 @@ public class Build extends BuildBase {
exclude("*.sh"). exclude("*.sh").
exclude("*.txt"). exclude("*.txt").
exclude("*.DS_Store"); exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
files.add(new File("temp/org/h2/tools/DeleteDbFiles.class")); files.add(new File("temp/org/h2/tools/DeleteDbFiles.class"));
files.add(new File("temp/org/h2/tools/CompressTool.class")); files.add(new File("temp/org/h2/tools/CompressTool.class"));
jar("bin/h2android" + getJarSuffix(), files, "temp"); jar("bin/h2android" + getJarSuffix(), files, "temp");
...@@ -479,6 +497,7 @@ public class Build extends BuildBase { ...@@ -479,6 +497,7 @@ public class Build extends BuildBase {
exclude("*.sh"). exclude("*.sh").
exclude("*.txt"). exclude("*.txt").
exclude("*.DS_Store"); exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
long kb = jar("bin/h2-client" + getJarSuffix(), files, "temp"); long kb = jar("bin/h2-client" + getJarSuffix(), files, "temp");
if (kb < 350 || kb > 450) { if (kb < 350 || kb > 450) {
throw new RuntimeException("Expected file size 350 - 450 KB, got: " + kb); throw new RuntimeException("Expected file size 350 - 450 KB, got: " + kb);
...@@ -493,6 +512,7 @@ public class Build extends BuildBase { ...@@ -493,6 +512,7 @@ public class Build extends BuildBase {
manifestMVStore(); manifestMVStore();
FileList files = files("temp"); FileList files = files("temp");
files.exclude("*.DS_Store"); files.exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
jar("bin/h2-mvstore" + getJarSuffix(), files, "temp"); jar("bin/h2-mvstore" + getJarSuffix(), files, "temp");
} }
...@@ -525,6 +545,7 @@ public class Build extends BuildBase { ...@@ -525,6 +545,7 @@ public class Build extends BuildBase {
exclude("*.sh"). exclude("*.sh").
exclude("*.txt"). exclude("*.txt").
exclude("*.DS_Store"); exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
files.add(new File("temp/org/h2/tools/DeleteDbFiles.class")); files.add(new File("temp/org/h2/tools/DeleteDbFiles.class"));
files.add(new File("temp/org/h2/tools/CompressTool.class")); files.add(new File("temp/org/h2/tools/CompressTool.class"));
jar("bin/h2small" + getJarSuffix(), files, "temp"); jar("bin/h2small" + getJarSuffix(), files, "temp");
...@@ -540,6 +561,7 @@ public class Build extends BuildBase { ...@@ -540,6 +561,7 @@ public class Build extends BuildBase {
FileList files = files("temp/org/h2/jaqu"); FileList files = files("temp/org/h2/jaqu");
files.addAll(files("temp/META-INF/MANIFEST.MF")); files.addAll(files("temp/META-INF/MANIFEST.MF"));
files.exclude("*.DS_Store"); files.exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
jar("bin/h2jaqu" + getJarSuffix(), files, "temp"); jar("bin/h2jaqu" + getJarSuffix(), files, "temp");
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论