提交 d802024e authored 作者: Owner's avatar Owner

Code is a mess - but solved main functional issues

上级 ab0708a7
...@@ -5153,7 +5153,7 @@ public class Parser { ...@@ -5153,7 +5153,7 @@ public class Parser {
// this keyword. This is a work in progress feature and will not be documented // this keyword. This is a work in progress feature and will not be documented
boolean isPersistent = readIf("PERSISTENT"); boolean isPersistent = readIf("PERSISTENT");
// this WITH statement is not be temporary - it is part of a persistent view // this WITH statement is not a temporary view - it is part of a persistent view
// as in CREATE VIEW abc AS WITH my_cte - this auto detects that condition // as in CREATE VIEW abc AS WITH my_cte - this auto detects that condition
if(session.isParsingView()){ if(session.isParsingView()){
isPersistent = true; isPersistent = true;
...@@ -5272,26 +5272,8 @@ public class Parser { ...@@ -5272,26 +5272,8 @@ public class Parser {
// to work (its removed after creation in this method) // to work (its removed after creation in this method)
// only create table data and table if we don't have a working CTE already // only create table data and table if we don't have a working CTE already
if(oldViewFound == null){ if(oldViewFound == null){
CreateTableData recursiveTableData = new CreateTableData(); recursiveTable = createShadowTableForRecursiveTableExpression(isPersistent, targetSession, cteViewName,
recursiveTableData.id = database.allocateObjectId(); schema, columns, db);
recursiveTableData.columns = columns;
recursiveTableData.tableName = cteViewName;
recursiveTableData.temporary = !isPersistent;
recursiveTableData.persistData = true;
recursiveTableData.persistIndexes = isPersistent;
recursiveTableData.create = true;
recursiveTableData.session = targetSession;
// this gets a meta table lock that is not released
recursiveTable = schema.createTable(recursiveTableData);
if(isPersistent){
// this unlock is to prevent lock leak from schema.createTable()
db.unlockMeta(targetSession);
synchronized (targetSession) {
db.addSchemaObject(targetSession, recursiveTable);
}
}else{
targetSession.addLocalTempTable(recursiveTable);
}
} }
List<Column> columnTemplateList; List<Column> columnTemplateList;
String[] querySQLOutput = new String[]{null}; String[] querySQLOutput = new String[]{null};
...@@ -5306,20 +5288,9 @@ public class Parser { ...@@ -5306,20 +5288,9 @@ public class Parser {
columnTemplateList = createQueryColumnTemplateList(cols, withQuery, querySQLOutput); columnTemplateList = createQueryColumnTemplateList(cols, withQuery, querySQLOutput);
} finally { } finally {
if(recursiveTable!=null){ destroyShadowTableForRecursiveExpression(isPersistent, targetSession, recursiveTable);
if(isPersistent){
recursiveTable.lock(targetSession, true, true);
targetSession.getDatabase().removeSchemaObject(targetSession, recursiveTable);
}else{
targetSession.removeLocalTempTable(recursiveTable);
}
}
} }
// If it's persistent, a CTE and a TableView - return existing one, otherwise create new...
//if(oldViewFound!=null && isPersistent && oldViewFound instanceof TableView && oldViewFound.isTableExpression()){
// return (TableView) oldViewFound;
//}
TableView view = createCTEView(cteViewName, TableView view = createCTEView(cteViewName,
querySQLOutput[0], columnTemplateList, querySQLOutput[0], columnTemplateList,
true/* allowRecursiveQueryDetection */, true/* add to session */, true/* allowRecursiveQueryDetection */, true/* add to session */,
...@@ -5328,6 +5299,48 @@ public class Parser { ...@@ -5328,6 +5299,48 @@ public class Parser {
return view; return view;
} }
public static void destroyShadowTableForRecursiveExpression(boolean isPersistent, Session targetSession,
Table recursiveTable) {
if(recursiveTable!=null){
if(isPersistent){
recursiveTable.lock(targetSession, true, true);
targetSession.getDatabase().removeSchemaObject(targetSession, recursiveTable);
}else{
targetSession.removeLocalTempTable(recursiveTable);
}
}
}
public static Table createShadowTableForRecursiveTableExpression(boolean isPersistent, Session targetSession,
String cteViewName, Schema schema, List<Column> columns, Database db) {
// create table data object
CreateTableData recursiveTableData = new CreateTableData();
recursiveTableData.id = db.allocateObjectId();
recursiveTableData.columns = new ArrayList<Column>(columns);
recursiveTableData.tableName = cteViewName;
recursiveTableData.temporary = !isPersistent;
recursiveTableData.persistData = true;
recursiveTableData.persistIndexes = isPersistent;
recursiveTableData.create = true;
recursiveTableData.session = targetSession;
// this gets a meta table lock that is not released
Table recursiveTable = schema.createTable(recursiveTableData);
if(isPersistent){
// this unlock is to prevent lock leak from schema.createTable()
db.unlockMeta(targetSession);
synchronized (targetSession) {
db.addSchemaObject(targetSession, recursiveTable);
}
}else{
targetSession.addLocalTempTable(recursiveTable);
}
return recursiveTable;
}
/** /**
* Creates a list of column templates from a query (usually from WITH query, * Creates a list of column templates from a query (usually from WITH query,
* but could be any query) * but could be any query)
...@@ -5365,8 +5378,6 @@ public class Parser { ...@@ -5365,8 +5378,6 @@ public class Parser {
private TableView createCTEView(String cteViewName, String querySQL, private TableView createCTEView(String cteViewName, String querySQL,
List<Column> columnTemplateList, boolean allowRecursiveQueryDetection, List<Column> columnTemplateList, boolean allowRecursiveQueryDetection,
boolean addViewToSession, boolean isPersistent, Session targetSession) { boolean addViewToSession, boolean isPersistent, Session targetSession) {
//Session targetSession = isPersistent ? database.getSystemSession() : session;
//Session targetSession = session;
Database db = targetSession.getDatabase(); Database db = targetSession.getDatabase();
Schema schema = getSchemaWithDefault(); Schema schema = getSchemaWithDefault();
int id = db.allocateObjectId(); int id = db.allocateObjectId();
......
...@@ -107,12 +107,19 @@ public class CreateView extends SchemaCommand { ...@@ -107,12 +107,19 @@ public class CreateView extends SchemaCommand {
if (columnNames != null) { if (columnNames != null) {
columnTemplates = new Column[columnNames.length]; columnTemplates = new Column[columnNames.length];
for (int i = 0; i < columnNames.length; ++i) { for (int i = 0; i < columnNames.length; ++i) {
columnTemplates[i] = new Column(columnNames[i], Value.UNKNOWN); columnTemplates[i] = new Column(columnNames[i], Value.STRING);
} }
} }
if (view == null) { if (view == null) {
view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false, false, isTableExpression); if(isTableExpression){
view = TableView.createTableViewMaybeRecursive(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false /* literalsChecked */, isTableExpression, true /*isPersistent*/ , db);
}
else
{
view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false/* allow recursive */, false/* literalsChecked */, isTableExpression);
}
} else { } else {
// TODO support isTableExpression in replace function...
view.replace(querySQL, columnTemplates, session, false, force, false); view.replace(querySQL, columnTemplates, session, false, force, false);
view.setModified(); view.setModified();
} }
...@@ -120,7 +127,6 @@ public class CreateView extends SchemaCommand { ...@@ -120,7 +127,6 @@ public class CreateView extends SchemaCommand {
view.setComment(comment); view.setComment(comment);
} }
if (old == null) { if (old == null) {
System.out.println("addSchemaObject="+view.getName()+",sessionId="+session.getId());
db.addSchemaObject(session, view); db.addSchemaObject(session, view);
db.unlockMeta(session); db.unlockMeta(session);
} else { } else {
......
...@@ -1239,13 +1239,6 @@ public class Select extends Query { ...@@ -1239,13 +1239,6 @@ public class Select extends Query {
return buff.toString(); return buff.toString();
} }
private String extractNamedCTEQueryFromSQL(String viewName, String sqlStatement) {
Table existingTableOrView = session.getDatabase().getSchema(session.getCurrentSchemaName()).findTableOrView(session, viewName);
TableView existingView = (TableView) existingTableOrView;
System.out.println("existingView.getSQL()="+existingView.getSQL());
return existingView.getSQL();
}
public void setHaving(Expression having) { public void setHaving(Expression having) {
this.having = having; this.having = having;
} }
......
...@@ -1071,6 +1071,8 @@ public class Database implements DataHandler { ...@@ -1071,6 +1071,8 @@ public class Database implements DataHandler {
* @param obj the object to add * @param obj the object to add
*/ */
public void addSchemaObject(Session session, SchemaObject obj) { public void addSchemaObject(Session session, SchemaObject obj) {
System.out.println("addSchemaObject="+obj.getName()+",sessionId="+session.getId()+",obj="+obj);
int id = obj.getId(); int id = obj.getId();
if (id > 0 && !starting) { if (id > 0 && !starting) {
checkWritingAllowed(); checkWritingAllowed();
...@@ -1909,7 +1911,7 @@ public class Database implements DataHandler { ...@@ -1909,7 +1911,7 @@ public class Database implements DataHandler {
int type = obj.getType(); int type = obj.getType();
if (type == DbObject.TABLE_OR_VIEW) { if (type == DbObject.TABLE_OR_VIEW) {
Table table = (Table) obj; Table table = (Table) obj;
table.setBeingDropped(true); //table.setBeingDropped(true);
if (table.isTemporary() && !table.isGlobalTemporary()) { if (table.isTemporary() && !table.isGlobalTemporary()) {
session.removeLocalTempTable(table); session.removeLocalTempTable(table);
return true; return true;
...@@ -1954,7 +1956,10 @@ public class Database implements DataHandler { ...@@ -1954,7 +1956,10 @@ public class Database implements DataHandler {
obj.removeChildrenAndResources(session); obj.removeChildrenAndResources(session);
} }
System.out.println("Removing db object id - also remove meta lock from session and session lock from meta, id="+id+",sessionId="+session.getId()+",name="+savedName); else{
System.out.println("Starting database detected");
}
System.out.println("Removing db object id - also remove meta lock from session and session lock from meta, id="+id+",sessionId="+session.getId()+",name="+savedName+",obj="+obj);
if("TREE_CTE".equals(savedName)){ if("TREE_CTE".equals(savedName)){
new RuntimeException("TREE_CTE distruction").printStackTrace(); new RuntimeException("TREE_CTE distruction").printStackTrace();
} }
......
...@@ -173,7 +173,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -173,7 +173,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
Prepared p; Prepared p;
session.pushSubQueryInfo(masks, filters, filter, sortOrder); session.pushSubQueryInfo(masks, filters, filter, sortOrder);
try { try {
System.out.println("ViewIndex.prepareSubQuery:"+sql); //System.out.println("ViewIndex.prepareSubQuery:"+sql);
p = session.prepare(sql, true, true); p = session.prepare(sql, true, true);
} finally { } finally {
session.popSubQueryInfo(); session.popSubQueryInfo();
......
...@@ -87,7 +87,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -87,7 +87,7 @@ public abstract class Table extends SchemaObjectBase {
private boolean onCommitDrop, onCommitTruncate; private boolean onCommitDrop, onCommitTruncate;
private volatile Row nullRow; private volatile Row nullRow;
private boolean tableExpression; private boolean tableExpression;
private boolean isBeingDropped; // private boolean isBeingDropped;
public Table(Schema schema, int id, String name, boolean persistIndexes, public Table(Schema schema, int id, String name, boolean persistIndexes,
...@@ -529,6 +529,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -529,6 +529,7 @@ public abstract class Table extends SchemaObjectBase {
public void removeChildrenAndResources(Session session) { public void removeChildrenAndResources(Session session) {
while (dependentViews.size() > 0) { while (dependentViews.size() > 0) {
TableView view = dependentViews.get(0); TableView view = dependentViews.get(0);
System.out.println("removeChildrenAndResources.dependentViews:"+view.getName());
dependentViews.remove(0); dependentViews.remove(0);
database.removeSchemaObject(session, view); database.removeSchemaObject(session, view);
} }
...@@ -840,7 +841,9 @@ public abstract class Table extends SchemaObjectBase { ...@@ -840,7 +841,9 @@ public abstract class Table extends SchemaObjectBase {
* @param view the view to remove * @param view the view to remove
*/ */
public void removeDependentView(TableView view) { public void removeDependentView(TableView view) {
System.out.println("removeDependentView(Before):"+dependentViews.toString());
dependentViews.remove(view); dependentViews.remove(view);
System.out.println("removeDependentView(Left):"+dependentViews.toString());
} }
/** /**
...@@ -1249,12 +1252,12 @@ public abstract class Table extends SchemaObjectBase { ...@@ -1249,12 +1252,12 @@ public abstract class Table extends SchemaObjectBase {
return tableExpression; return tableExpression;
} }
public boolean isBeingDropped(){ // public boolean isBeingDropped(){
return isBeingDropped; // return isBeingDropped;
} // }
//
public void setBeingDropped(boolean isBeingDropped){ // public void setBeingDropped(boolean isBeingDropped){
this.isBeingDropped = isBeingDropped; // this.isBeingDropped = isBeingDropped;
} // }
} }
...@@ -11,6 +11,7 @@ import java.util.HashSet; ...@@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.List; 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.Parser;
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;
...@@ -51,7 +52,7 @@ public class TableView extends Table { ...@@ -51,7 +52,7 @@ public class TableView extends Table {
private Column[] columnTemplates; private Column[] columnTemplates;
private Query viewQuery; private Query viewQuery;
private ViewIndex index; private ViewIndex index;
private boolean recursive; private boolean allowRecursive;
private DbException createException; private DbException createException;
private long lastModificationCheck; private long lastModificationCheck;
private long maxDataModificationId; private long maxDataModificationId;
...@@ -64,9 +65,9 @@ public class TableView extends Table { ...@@ -64,9 +65,9 @@ public class TableView extends Table {
public TableView(Schema schema, int id, String name, String querySQL, public TableView(Schema schema, int id, String name, String querySQL,
ArrayList<Parameter> params, Column[] columnTemplates, Session session, ArrayList<Parameter> params, Column[] columnTemplates, Session session,
boolean recursive, boolean literalsChecked, boolean isTableExpression) { boolean allowRecursive, boolean literalsChecked, boolean isTableExpression) {
super(schema, id, name, false, true); super(schema, id, name, false, true);
init(querySQL, params, columnTemplates, session, recursive, literalsChecked, isTableExpression); init(querySQL, params, columnTemplates, session, allowRecursive, literalsChecked, isTableExpression);
} }
/** /**
...@@ -82,7 +83,7 @@ public class TableView extends Table { ...@@ -82,7 +83,7 @@ public class TableView extends Table {
boolean recursive, boolean force, boolean literalsChecked) { boolean recursive, boolean force, boolean literalsChecked) {
String oldQuerySQL = this.querySQL; String oldQuerySQL = this.querySQL;
Column[] oldColumnTemplates = this.columnTemplates; Column[] oldColumnTemplates = this.columnTemplates;
boolean oldRecursive = this.recursive; boolean oldRecursive = this.allowRecursive;
init(querySQL, null, init(querySQL, null,
newColumnTemplates == null ? this.columnTemplates newColumnTemplates == null ? this.columnTemplates
: newColumnTemplates, : newColumnTemplates,
...@@ -97,14 +98,14 @@ public class TableView extends Table { ...@@ -97,14 +98,14 @@ public class TableView extends Table {
} }
private synchronized void init(String querySQL, ArrayList<Parameter> params, private synchronized void init(String querySQL, ArrayList<Parameter> params,
Column[] columnTemplates, Session session, boolean recursive, boolean literalsChecked, boolean isTableExpression) { Column[] columnTemplates, Session session, boolean allowRecursive, boolean literalsChecked, boolean isTableExpression) {
this.querySQL = querySQL; this.querySQL = querySQL;
this.columnTemplates = columnTemplates; this.columnTemplates = columnTemplates;
this.recursive = recursive; this.allowRecursive = allowRecursive;
this.isRecursiveQueryDetected = false; this.isRecursiveQueryDetected = false;
this.isTableExpression = isTableExpression; this.isTableExpression = isTableExpression;
//this.session = session; //this.session = session;
index = new ViewIndex(this, querySQL, params, recursive); index = new ViewIndex(this, querySQL, params, allowRecursive);
initColumnsAndTables(session, literalsChecked); initColumnsAndTables(session, literalsChecked);
} }
...@@ -156,7 +157,7 @@ public class TableView extends Table { ...@@ -156,7 +157,7 @@ public class TableView extends Table {
private void initColumnsAndTables(Session session, boolean literalsChecked) { private void initColumnsAndTables(Session session, boolean literalsChecked) {
Column[] cols; Column[] cols;
removeDependentViewFromTables(); removeCurrentViewFromOtherTables();
setTableExpression(isTableExpression); setTableExpression(isTableExpression);
try { try {
Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked, getName()); Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked, getName());
...@@ -221,7 +222,7 @@ public class TableView extends Table { ...@@ -221,7 +222,7 @@ public class TableView extends Table {
} }
tables = New.arrayList(); tables = New.arrayList();
cols = new Column[0]; cols = new Column[0];
if (recursive && columnTemplates != null) { if (allowRecursive && columnTemplates != null) {
cols = new Column[columnTemplates.length]; cols = new Column[columnTemplates.length];
for (int i = 0; i < columnTemplates.length; i++) { for (int i = 0; i < columnTemplates.length; i++) {
cols[i] = columnTemplates[i].getClone(); cols[i] = columnTemplates[i].getClone();
...@@ -426,7 +427,7 @@ public class TableView extends Table { ...@@ -426,7 +427,7 @@ public class TableView extends Table {
@Override @Override
public void removeChildrenAndResources(Session session) { public void removeChildrenAndResources(Session session) {
removeDependentViewFromTables(); removeCurrentViewFromOtherTables();
super.removeChildrenAndResources(session); super.removeChildrenAndResources(session);
database.removeMeta(session, getId()); database.removeMeta(session, getId());
querySQL = null; querySQL = null;
...@@ -510,9 +511,10 @@ public class TableView extends Table { ...@@ -510,9 +511,10 @@ public class TableView extends Table {
return null; return null;
} }
private void removeDependentViewFromTables() { private void removeCurrentViewFromOtherTables() {
if (tables != null) { if (tables != null) {
for (Table t : tables) { for (Table t : tables) {
System.out.println("removeCurrentViewFromOtherTables:"+t.getName());
t.removeDependentView(this); t.removeDependentView(this);
} }
tables.clear(); tables.clear();
...@@ -596,12 +598,12 @@ public class TableView extends Table { ...@@ -596,12 +598,12 @@ public class TableView extends Table {
} }
public boolean isRecursive() { public boolean isRecursive() {
return recursive; return allowRecursive;
} }
@Override @Override
public boolean isDeterministic() { public boolean isDeterministic() {
if (recursive || viewQuery == null) { if (allowRecursive || viewQuery == null) {
return false; return false;
} }
return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC_VISITOR); return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC_VISITOR);
...@@ -703,17 +705,38 @@ public class TableView extends Table { ...@@ -703,17 +705,38 @@ public class TableView extends Table {
return tables; return tables;
} }
// @Override public static TableView createTableViewMaybeRecursive(Schema schema, int id, String name, String querySQL,
// public void removeView(TableView view){ ArrayList<Parameter> parameters, Column[] columnTemplates, Session session,
// super.removeView(view); boolean literalsChecked, boolean isTableExpression, boolean isPersistent, Database db){
// // if this is a table expression and the last view to use it is
// // being dropped - then remove itself from the schema //Table shadowTable = Parser.createShadowTableForRecursiveTableExpression(isPersistent, session, name, schema, Arrays.asList(columnTemplates), db);
// if(isTableExpression() && getViews()!=null){
// // check if any database objects are left using this view TableView view = new TableView(schema, id, name, querySQL,
// if(getViews().size()==0 && !isBeingDropped()){ parameters, columnTemplates, session,
// System.out.println("Detected unused CTE: Trying to remove="+this.getName()+",session="+session.toString()+",sessionId="+session.getId()); true/* try recursive */, literalsChecked, isTableExpression );
// session.getDatabase().removeSchemaObject(session,this); System.out.println("create recursive view:"+view);
// }
// } //if(shadowTable!=null){
// } // Parser.destroyShadowTableForRecursiveExpression(isPersistent, session, shadowTable);
//}
System.out.println("view.isRecursiveQueryDetected()="+view.isRecursiveQueryDetected());
// is not recursion detected ? if so - recreate it without recursion flag
if (!view.isRecursiveQueryDetected()) {
if(isPersistent){
db.addSchemaObject(session, view);
view.lock(session, true, true);
session.getDatabase().removeSchemaObject(session, view);
view.removeChildrenAndResources(session);
}else{
session.removeLocalTempTable(view);
}
view = new TableView(schema, id, name, querySQL, parameters,
columnTemplates, session,
false/* detected not recursive */, literalsChecked, isTableExpression);
System.out.println("create nr view:"+view);
}
return view;
}
} }
...@@ -29,20 +29,20 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -29,20 +29,20 @@ public class TestGeneralCommonTableQueries extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
// testSimpleSelect(); testSimpleSelect();
// testImpliedColumnNames(); testImpliedColumnNames();
// testChainedQuery(); testChainedQuery();
// testParameterizedQuery(); testParameterizedQuery();
// testNumberedParameterizedQuery(); testNumberedParameterizedQuery();
// testColumnNames(); testColumnNames();
//
// testInsert(); testInsert();
// testUpdate(); testUpdate();
// testDelete(); testDelete();
// testMerge(); testMerge();
// testCreateTable(); testCreateTable();
// testNestedSQL(); testNestedSQL();
// testRecursiveTable(); testRecursiveTable();
// turn on special locking debug // turn on special locking debug
System.setProperty("h2.check2", "true"); System.setProperty("h2.check2", "true");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论