提交 94e79df5 authored 作者: Owner's avatar Owner

Issue#479 Ready for final fix to testCTE

上级 8ca2feb0
...@@ -76,7 +76,6 @@ import org.h2.command.dml.Insert; ...@@ -76,7 +76,6 @@ import org.h2.command.dml.Insert;
import org.h2.command.dml.Merge; import org.h2.command.dml.Merge;
import org.h2.command.dml.NoOperation; import org.h2.command.dml.NoOperation;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.command.dml.RecursiveQueryHeuristic;
import org.h2.command.dml.Replace; import org.h2.command.dml.Replace;
import org.h2.command.dml.RunScriptCommand; import org.h2.command.dml.RunScriptCommand;
import org.h2.command.dml.ScriptCommand; import org.h2.command.dml.ScriptCommand;
...@@ -126,7 +125,6 @@ import org.h2.expression.Variable; ...@@ -126,7 +125,6 @@ import org.h2.expression.Variable;
import org.h2.expression.Wildcard; import org.h2.expression.Wildcard;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.DbNotRecursiveException;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.schema.Sequence; import org.h2.schema.Sequence;
...@@ -4862,7 +4860,7 @@ public class Parser { ...@@ -4862,7 +4860,7 @@ public class Parser {
List<TableView> viewsCreated = new ArrayList<TableView>(); List<TableView> viewsCreated = new ArrayList<TableView>();
readIf("RECURSIVE"); readIf("RECURSIVE");
do{ do{
viewsCreated.add(parseSingleCommonTableExression()); viewsCreated.add(parseSingleCommonTableExpression());
} while(readIf(",")); } while(readIf(","));
Query q = parseSelectUnion(); Query q = parseSelectUnion();
...@@ -4870,7 +4868,7 @@ public class Parser { ...@@ -4870,7 +4868,7 @@ public class Parser {
return q; return q;
} }
private TableView parseSingleCommonTableExression() { private TableView parseSingleCommonTableExpression() {
String tempViewName = readIdentifierWithSchema(); String tempViewName = readIdentifierWithSchema();
Schema schema = getSchema(); Schema schema = getSchema();
Table recursiveTable; Table recursiveTable;
...@@ -4931,34 +4929,15 @@ public class Parser { ...@@ -4931,34 +4929,15 @@ public class Parser {
session.removeLocalTempTable(recursiveTable); session.removeLocalTempTable(recursiveTable);
} }
int id = database.allocateObjectId(); int id = database.allocateObjectId();
boolean isRecursive = true;//RecursiveQueryHeuristic.isRecursive(tempViewName,querySQL); boolean isRecursive = true;
TableView view = null; TableView view = null;
do{ do{
try{
view = new TableView(schema, id, tempViewName, querySQL, view = new TableView(schema, id, tempViewName, querySQL,
parameters, columnTemplateList.toArray(new Column[0]), session, parameters, columnTemplateList.toArray(new Column[0]), session,
isRecursive); isRecursive);
}catch(DbNotRecursiveException e){
if(isRecursive==false){
throw e;
}
isRecursive = false;
view=null;
System.out.println("repeat new table by exeception");
continue;
}
HashSet<DbObject> subDependencies = new HashSet<DbObject>();
view.addStrictSubDependencies(subDependencies,false);
System.out.println("tempViewName="+tempViewName);
System.out.println("subDependencies="+subDependencies);
System.out.println("isRecursiveQueryDetected="+view.isRecursiveQueryDetected());
boolean isRecursiveByDeepAnalysis = subDependencies.contains(recursiveTable);
System.out.println("isRecursiveByDeepAnalysis="+isRecursiveByDeepAnalysis);
if(view.isRecursiveQueryDetected()!=isRecursive){ if(view.isRecursiveQueryDetected()!=isRecursive){
isRecursive = view.isRecursiveQueryDetected(); isRecursive = view.isRecursiveQueryDetected();
view = null; view = null;
System.out.println("repeat new table creation by view.isRecursiveQueryDetected()");
continue; continue;
} }
......
package org.h2.command.dml;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RecursiveQueryHeuristic {
// A query is recursive if it references it's own name in its definition
public static boolean isRecursive(String tempViewName, String querySQL) {
boolean foundAny = RecursiveQueryHeuristic.foundAny(tempViewName,querySQL);
//System.out.println("foundAny="+foundAny);
return foundAny;
}
private static boolean foundAny(String tempViewName, String querySQL){
// ?i is case insensitive
// ?m is multi-line search
// ?d is Unix line endings
Pattern p = Pattern.compile("(?i)(?m)(?d)\\b("+tempViewName+")\\b");
Matcher m = p.matcher(querySQL);
while (m.find()) {
return true;
}
return false;
}
}
...@@ -19,7 +19,6 @@ import org.h2.engine.Session; ...@@ -19,7 +19,6 @@ import org.h2.engine.Session;
import org.h2.expression.Comparison; import org.h2.expression.Comparison;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.DbNotRecursiveException;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.result.Row; import org.h2.result.Row;
...@@ -196,12 +195,12 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -196,12 +195,12 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
query.setNeverLazy(true); query.setNeverLazy(true);
} }
if (!query.isUnion()) { if (!query.isUnion()) {
throw DbNotRecursiveException.get(ErrorCode.SYNTAX_ERROR_2, throw DbException.get(ErrorCode.SYNTAX_ERROR_2,
"recursive queries without UNION ALL"); "recursive queries without UNION ALL");
} }
SelectUnion union = (SelectUnion) query; SelectUnion union = (SelectUnion) query;
if (union.getUnionType() != SelectUnion.UNION_ALL) { if (union.getUnionType() != SelectUnion.UNION_ALL) {
throw DbNotRecursiveException.get(ErrorCode.SYNTAX_ERROR_2, throw DbException.get(ErrorCode.SYNTAX_ERROR_2,
"recursive queries without UNION ALL"); "recursive queries without UNION ALL");
} }
Query left = union.getLeft(); Query left = union.getLeft();
......
...@@ -70,11 +70,11 @@ public class DbException extends RuntimeException { ...@@ -70,11 +70,11 @@ public class DbException extends RuntimeException {
} }
} }
protected DbException(SQLException e) { private DbException(SQLException e) {
super(e.getMessage(), e); super(e.getMessage(), e);
} }
protected static String translate(String key, String... params) { private static String translate(String key, String... params) {
String message = null; String message = null;
if (MESSAGES != null) { if (MESSAGES != null) {
// Tomcat sets final static fields to null sometimes // Tomcat sets final static fields to null sometimes
......
package org.h2.message;
import java.sql.SQLException;
import org.h2.api.ErrorCode;
import org.h2.jdbc.JdbcSQLException;
public class DbNotRecursiveException extends DbException {
private static final long serialVersionUID = -5941745175474148318L;
public static DbNotRecursiveException get(int errorCode, String p1) {
return get(errorCode, new String[] { p1 });
}
public static DbNotRecursiveException get(int errorCode, String... params) {
return new DbNotRecursiveException(getJdbcSQLException(errorCode, null, params));
}
private static JdbcSQLException getJdbcSQLException(int errorCode,
Throwable cause, String... params) {
String sqlstate = ErrorCode.getState(errorCode);
String message = translate(sqlstate, params);
return new JdbcSQLException(message, null, sqlstate, errorCode, cause, null);
}
private DbNotRecursiveException(SQLException e) {
super(e);
}
}
...@@ -145,7 +145,6 @@ public class RangeTable extends Table { ...@@ -145,7 +145,6 @@ public class RangeTable extends Table {
@Override @Override
public TableType getTableType() { public TableType getTableType() {
return TableType.SYSTEM_TABLE; return TableType.SYSTEM_TABLE;
//throw DbException.throwInternalError(toString());
} }
@Override @Override
......
...@@ -352,23 +352,12 @@ public abstract class Table extends SchemaObjectBase { ...@@ -352,23 +352,12 @@ public abstract class Table extends SchemaObjectBase {
} }
/** /**
* Add all objects that this table depends on to the hash set, including this object. * Add all objects that this table depends on to the hash set.
* *
* @param dependencies the current set of dependencies * @param dependencies the current set of dependencies
*/ */
public void addDependencies(HashSet<DbObject> dependencies) { public void addDependencies(HashSet<DbObject> dependencies) {
addStrictSubDependencies(dependencies,false); if (dependencies.contains(this)) {
dependencies.add(this);
}
/**
* Add all objects that this table depends on to the hash set, excluding
* this object (unless it is has recursive references).
*
* @param dependencies the current set of dependencies
*/
public void addStrictSubDependencies(HashSet<DbObject> dependencies, boolean visitColumnTables) {
if (dependencies.contains(this)) {
// avoid endless recursion // avoid endless recursion
return; return;
} }
...@@ -381,16 +370,14 @@ public abstract class Table extends SchemaObjectBase { ...@@ -381,16 +370,14 @@ public abstract class Table extends SchemaObjectBase {
dependencies); dependencies);
for (Column col : columns) { for (Column col : columns) {
col.isEverything(visitor); col.isEverything(visitor);
if(visitColumnTables && col.getTable()!=null){
dependencies.add(col.getTable());
}
} }
if (constraints != null) { if (constraints != null) {
for (Constraint c : constraints) { for (Constraint c : constraints) {
c.isEverything(visitor); c.isEverything(visitor);
} }
} }
} dependencies.add(this);
}
@Override @Override
public ArrayList<DbObject> getChildren() { public ArrayList<DbObject> getChildren() {
......
...@@ -8,9 +8,7 @@ package org.h2.table; ...@@ -8,9 +8,7 @@ package org.h2.table;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.h2.api.ErrorCode; 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;
...@@ -210,6 +208,8 @@ public class TableView extends Table { ...@@ -210,6 +208,8 @@ public class TableView extends Table {
// if it can't be compiled, then it's a 'zero column table' // if it can't be compiled, then it's a 'zero column table'
// this avoids problems when creating the view when opening the // this avoids problems when creating the view when opening the
// database // database
// if it can not be compiled - it could also be a recursive common table expression query
if(isRecursiveQueryExceptionDetected(createException)){ if(isRecursiveQueryExceptionDetected(createException)){
this.isRecursiveQueryDetected = true; this.isRecursiveQueryDetected = true;
} }
...@@ -674,19 +674,17 @@ public class TableView extends Table { ...@@ -674,19 +674,17 @@ public class TableView extends Table {
} }
/** /**
* Get a list of the tables used by this query (for recursion detection) * If query recursion is detected (for recursion detection)
* @return * @return is Recursive Query Flag Set
*/ */
public List<Table> getTables(){
return tables;
}
public boolean isRecursiveQueryDetected(){ public boolean isRecursiveQueryDetected(){
return isRecursiveQueryDetected; return isRecursiveQueryDetected;
} }
/**
* If query an exception indicates query recursion
* @return is Recursive Query Exception Detected
*/
private boolean isRecursiveQueryExceptionDetected(DbException exception){ private boolean isRecursiveQueryExceptionDetected(DbException exception){
if (exception==null){ if (exception==null){
return false; return false;
......
...@@ -51,9 +51,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -51,9 +51,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
* @param a ignored * @param a ignored
*/ */
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
System.out.println("Testing starting");
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
System.out.println("Testing done");
} }
@Override @Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论