提交 8ca2feb0 authored 作者: Owner's avatar Owner

Issue#479 Intermediate save before refactor to remove heuristic

上级 f21ea8cd
......@@ -199,10 +199,10 @@ WITH [ RECURSIVE ] { name [( columnName [,...] )]
","
Can be used to create a recursive query.
For recursive queries the first select has to be a UNION.
Non-recursive queries are also supported,
One or more common table entries can be use referred to by name.
Non-recursive queries are also supported.
One or more common table entries can be use referred to by name..
Column name declarations are now optional - the column names will be inferred from the named select queries.
Positional parameters are not currently correctly supported.
Positional parameters are not currently supported.
","
WITH RECURSIVE t(n) AS (
SELECT 1
......
......@@ -76,7 +76,7 @@ import org.h2.command.dml.Insert;
import org.h2.command.dml.Merge;
import org.h2.command.dml.NoOperation;
import org.h2.command.dml.Query;
import org.h2.command.dml.RecursiveQuery;
import org.h2.command.dml.RecursiveQueryHeuristic;
import org.h2.command.dml.Replace;
import org.h2.command.dml.RunScriptCommand;
import org.h2.command.dml.ScriptCommand;
......@@ -126,6 +126,7 @@ import org.h2.expression.Variable;
import org.h2.expression.Wildcard;
import org.h2.index.Index;
import org.h2.message.DbException;
import org.h2.message.DbNotRecursiveException;
import org.h2.result.SortOrder;
import org.h2.schema.Schema;
import org.h2.schema.Sequence;
......@@ -4930,10 +4931,38 @@ public class Parser {
session.removeLocalTempTable(recursiveTable);
}
int id = database.allocateObjectId();
boolean isRecursive = RecursiveQuery.isRecursive(tempViewName,querySQL);
TableView view = new TableView(schema, id, tempViewName, querySQL,
boolean isRecursive = true;//RecursiveQueryHeuristic.isRecursive(tempViewName,querySQL);
TableView view = null;
do{
try{
view = new TableView(schema, id, tempViewName, querySQL,
parameters, columnTemplateList.toArray(new Column[0]), session,
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){
isRecursive = view.isRecursiveQueryDetected();
view = null;
System.out.println("repeat new table creation by view.isRecursiveQueryDetected()");
continue;
}
} while(view==null);
view.setTableExpression(true);
view.setTemporary(true);
session.addLocalTempTable(view);
......
......@@ -3,11 +3,11 @@ package org.h2.command.dml;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RecursiveQuery {
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 = RecursiveQuery.foundAny(tempViewName,querySQL);
boolean foundAny = RecursiveQueryHeuristic.foundAny(tempViewName,querySQL);
//System.out.println("foundAny="+foundAny);
return foundAny;
}
......
......@@ -19,6 +19,7 @@ import org.h2.engine.Session;
import org.h2.expression.Comparison;
import org.h2.expression.Parameter;
import org.h2.message.DbException;
import org.h2.message.DbNotRecursiveException;
import org.h2.result.LocalResult;
import org.h2.result.ResultInterface;
import org.h2.result.Row;
......@@ -195,12 +196,12 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
query.setNeverLazy(true);
}
if (!query.isUnion()) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_2,
throw DbNotRecursiveException.get(ErrorCode.SYNTAX_ERROR_2,
"recursive queries without UNION ALL");
}
SelectUnion union = (SelectUnion) query;
if (union.getUnionType() != SelectUnion.UNION_ALL) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_2,
throw DbNotRecursiveException.get(ErrorCode.SYNTAX_ERROR_2,
"recursive queries without UNION ALL");
}
Query left = union.getLeft();
......
......@@ -70,11 +70,11 @@ public class DbException extends RuntimeException {
}
}
private DbException(SQLException e) {
protected DbException(SQLException e) {
super(e.getMessage(), e);
}
private static String translate(String key, String... params) {
protected static String translate(String key, String... params) {
String message = null;
if (MESSAGES != null) {
// 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);
}
}
......@@ -738,9 +738,6 @@ public class Column {
public String toString() {
return name;
}
public String toStringWithType() {
return DataType.getTypeClassName(type)+":"+name;
}
/**
* Check whether the new column is of the same type and not more restricted
......
......@@ -144,7 +144,8 @@ public class RangeTable extends Table {
@Override
public TableType getTableType() {
throw DbException.throwInternalError(toString());
return TableType.SYSTEM_TABLE;
//throw DbException.throwInternalError(toString());
}
@Override
......
......@@ -352,12 +352,23 @@ public abstract class Table extends SchemaObjectBase {
}
/**
* Add all objects that this table depends on to the hash set.
* Add all objects that this table depends on to the hash set, including this object.
*
* @param dependencies the current set of dependencies
*/
public void addDependencies(HashSet<DbObject> dependencies) {
if (dependencies.contains(this)) {
addStrictSubDependencies(dependencies,false);
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
return;
}
......@@ -370,14 +381,16 @@ public abstract class Table extends SchemaObjectBase {
dependencies);
for (Column col : columns) {
col.isEverything(visitor);
if(visitColumnTables && col.getTable()!=null){
dependencies.add(col.getTable());
}
}
if (constraints != null) {
for (Constraint c : constraints) {
c.isEverything(visitor);
}
}
dependencies.add(this);
}
}
@Override
public ArrayList<DbObject> getChildren() {
......
......@@ -8,7 +8,9 @@ package org.h2.table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.command.dml.Query;
......@@ -57,6 +59,7 @@ public class TableView extends Table {
private Query topQuery;
private ResultInterface recursiveResult;
private boolean tableExpression;
private boolean isRecursiveQueryDetected;
public TableView(Schema schema, int id, String name, String querySQL,
ArrayList<Parameter> params, Column[] columnTemplates, Session session,
......@@ -94,6 +97,7 @@ public class TableView extends Table {
this.querySQL = querySQL;
this.columnTemplates = columnTemplates;
this.recursive = recursive;
this.isRecursiveQueryDetected = false;
index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session);
}
......@@ -206,6 +210,9 @@ public class TableView extends Table {
// if it can't be compiled, then it's a 'zero column table'
// this avoids problems when creating the view when opening the
// database
if(isRecursiveQueryExceptionDetected(createException)){
this.isRecursiveQueryDetected = true;
}
tables = New.arrayList();
cols = new Column[0];
if (recursive && columnTemplates != null) {
......@@ -665,5 +672,32 @@ public class TableView extends Table {
return true;
}
}
/**
* Get a list of the tables used by this query (for recursion detection)
* @return
*/
public List<Table> getTables(){
return tables;
}
public boolean isRecursiveQueryDetected(){
return isRecursiveQueryDetected;
}
private boolean isRecursiveQueryExceptionDetected(DbException exception){
if (exception==null){
return false;
}
if (exception.getErrorCode()!=ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1){
return false;
}
if (! exception.getMessage().contains("\""+this.getName()+"\"")){
return false;
}
return true;
}
}
......@@ -51,8 +51,9 @@ public class TestGeneralCommonTableQueries extends TestBase {
* @param a ignored
*/
public static void main(String... a) throws Exception {
System.out.println("Testing starting");
TestBase.createCaller().init().test();
//System.out.println("Testing done");
System.out.println("Testing done");
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论