提交 8537c549 authored 作者: Owner's avatar Owner

Issue#573 Remove temp views for CTEs in WITH statement

上级 d351a574
......@@ -7,6 +7,8 @@ package org.h2.command;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Database;
......@@ -45,6 +47,8 @@ public abstract class Command implements CommandInterface {
private boolean canReuse;
private List<Runnable> cleanupCallbacks;
Command(Parser parser, String sql) {
this.session = parser.getSession();
this.sql = sql;
......@@ -228,6 +232,7 @@ public abstract class Command implements CommandInterface {
throw e;
} finally {
if (callStop) {
commandCleanup();
stop();
}
if (writing) {
......@@ -287,6 +292,7 @@ public abstract class Command implements CommandInterface {
} finally {
try {
if (callStop) {
commandCleanup();
stop();
}
} finally {
......@@ -298,6 +304,17 @@ public abstract class Command implements CommandInterface {
}
}
private void commandCleanup() {
if (cleanupCallbacks!=null){
for(Runnable eachCleanup:cleanupCallbacks){
eachCleanup.run();
// clean up done - must restart query (and dependency construction) to reuse
canReuse = false;
}
cleanupCallbacks.clear();
}
}
private long filterConcurrentUpdate(DbException e, long start) {
int errorCode = e.getErrorCode();
if (errorCode != ErrorCode.CONCURRENT_UPDATE_1 &&
......@@ -370,4 +387,8 @@ public abstract class Command implements CommandInterface {
}
}
public void setCleanupCallbacks(List<Runnable> cleanupCallbacks) {
this.cleanupCallbacks = cleanupCallbacks;
}
}
......@@ -4899,6 +4899,26 @@ public class Parser {
Query q = parseSelectUnion();
q.setPrepareAlways(true);
List<Runnable> cleanupCallbacks = new ArrayList<Runnable>();
// clean up temp views starting with last to first (in case of dependencies)
Collections.reverse(viewsCreated);
for (TableView view : viewsCreated){
if(view==null){
continue;
}
cleanupCallbacks.add(new Runnable(){
@Override
public void run() {
// check if view was previously deleted as their name is set to null
if(view.getName()!=null) {
session.removeLocalTempTable(view);
}
}
});
}
q.setCleanupCallbacks(cleanupCallbacks);
return q;
}
......
......@@ -6,6 +6,8 @@
package org.h2.command;
import java.util.ArrayList;
import java.util.List;
import org.h2.api.DatabaseEventListener;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
......@@ -55,6 +57,7 @@ public abstract class Prepared {
private int objectId;
private int currentRowNumber;
private int rowScanCount;
private List<Runnable> cleanupCallbacks;
/**
* Create a new object.
......@@ -173,6 +176,9 @@ public abstract class Prepared {
*/
public void setCommand(Command command) {
this.command = command;
if(command!=null && cleanupCallbacks!=null){
command.setCleanupCallbacks(cleanupCallbacks);
}
}
/**
......@@ -434,4 +440,13 @@ public abstract class Prepared {
return false;
}
public List<Runnable> getCleanupCallbacks() {
return cleanupCallbacks;
}
public void setCleanupCallbacks(List<Runnable> cleanupCallbacks) {
this.cleanupCallbacks = cleanupCallbacks;
}
}
......@@ -381,6 +381,12 @@ SET BINARY_COLLATION
","
Sets the collation used for comparing BINARY columns, the default is SIGNED
for version 1."
"Commands (Other)","SET BUILTIN_ALIAS_OVERRIDE","
SET BUILTIN_ALIAS_OVERRIDE
{ TRUE | FALSE } ] }
","
Allows the overriding of the builtin system date/time functions
for unit testing purposes."
"Commands (Other)","SET COLLATION","
SET [ DATABASE ] COLLATION
{ OFF | collationName [ STRENGTH { PRIMARY | SECONDARY | TERTIARY | IDENTICAL } ] }
......
......@@ -9,6 +9,8 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.jdbc.JdbcSQLException;
import org.h2.test.TestBase;
/**
......@@ -186,6 +188,8 @@ public class TestGeneralCommonTableQueries extends TestBase {
PreparedStatement prep;
ResultSet rs;
conn.setAutoCommit(false);
prep = conn.prepareStatement("WITH t1 AS ("
+" SELECT R.X, 'T1' FROM SYSTEM_RANGE(?1,?2) R"
+"),"
......@@ -210,6 +214,16 @@ public class TestGeneralCommonTableQueries extends TestBase {
assertFalse(rs.next());
try{
prep = conn.prepareStatement("SELECT * FROM t1 UNION ALL SELECT * FROM t2 UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(5,6)");
rs = prep.executeQuery();
fail("Temp view T1 was accessible after previous WITH statement finished - but should not have been.");
}
catch(JdbcSQLException e){
// ensure the T1 table has been removed even without auto commit
assertContains(e.getMessage(),"Table \"T1\" not found;");
}
conn.close();
deleteDb("commonTableExpressionQueries");
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论