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

Code is a mess - but solved main functional issues

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