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

Got database loading working for non recursive table expressions

上级 e83c133c
...@@ -1142,7 +1142,8 @@ public class Parser { ...@@ -1142,7 +1142,8 @@ public class Parser {
command.getQueryAlias(), querySQLOutput[0], command.getQueryAlias(), querySQLOutput[0],
columnTemplateList, false/* no recursion */, columnTemplateList, false/* no recursion */,
false/* do not add to session */, false/* do not add to session */,
false /* isPersistent */); false /* isPersistent */,
session);
TableFilter sourceTableFilter = new TableFilter(session, TableFilter sourceTableFilter = new TableFilter(session,
temporarySourceTableView, command.getQueryAlias(), temporarySourceTableView, command.getQueryAlias(),
rightsChecked, (Select) command.getQuery(), 0, null); rightsChecked, (Select) command.getQuery(), 0, null);
...@@ -5212,9 +5213,10 @@ public class Parser { ...@@ -5212,9 +5213,10 @@ public class Parser {
return p; return p;
} }
@SuppressWarnings("resource")// Eclipse thinks targetSession needs releasing //@SuppressWarnings("resource")// Eclipse thinks targetSession needs releasing
private TableView parseSingleCommonTableExpression(boolean isPersistent) { private TableView parseSingleCommonTableExpression(boolean isPersistent) {
Session targetSession = isPersistent ? database.getSystemSession() : session; //Session targetSession = isPersistent ? database.getSystemSession() : session;
Session targetSession = session;
String cteViewName = readIdentifierWithSchema(); String cteViewName = readIdentifierWithSchema();
Schema schema = getSchema(); Schema schema = getSchema();
Table recursiveTable=null; Table recursiveTable=null;
...@@ -5243,7 +5245,8 @@ public class Parser { ...@@ -5243,7 +5245,8 @@ public class Parser {
else{ else{
oldViewFound = targetSession.findLocalTempTable(cteViewName); oldViewFound = targetSession.findLocalTempTable(cteViewName);
} }
if (oldViewFound != null && !isPersistent) { // this persistent check conflicts with check 10 lines down
if (oldViewFound != null) {
if (!(oldViewFound instanceof TableView)) { if (!(oldViewFound instanceof TableView)) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1,
cteViewName); cteViewName);
...@@ -5254,6 +5257,7 @@ public class Parser { ...@@ -5254,6 +5257,7 @@ public class Parser {
cteViewName); cteViewName);
} }
if(isPersistent){ if(isPersistent){
System.out.println("parseSingleCommonTableExpression removeSchemaObject "+oldViewFound.getName());
oldViewFound.lock(targetSession, true, true); oldViewFound.lock(targetSession, true, true);
targetSession.getDatabase().removeSchemaObject(targetSession, oldViewFound); targetSession.getDatabase().removeSchemaObject(targetSession, oldViewFound);
...@@ -5313,12 +5317,13 @@ public class Parser { ...@@ -5313,12 +5317,13 @@ public class Parser {
} }
} }
// If it's persistent, a CTE and a TableView - return existing one, otherwise create new... // If it's persistent, a CTE and a TableView - return existing one, otherwise create new...
if(oldViewFound!=null && isPersistent && oldViewFound instanceof TableView && oldViewFound.isTableExpression()){ //if(oldViewFound!=null && isPersistent && oldViewFound instanceof TableView && oldViewFound.isTableExpression()){
return (TableView) oldViewFound; // return (TableView) oldViewFound;
} //}
TableView view = createCTEView(cteViewName, TableView view = createCTEView(cteViewName,
querySQLOutput[0], columnTemplateList, querySQLOutput[0], columnTemplateList,
true/* allowRecursiveQueryDetection */, true/* add to session */, isPersistent); true/* allowRecursiveQueryDetection */, true/* add to session */,
isPersistent, targetSession);
return view; return view;
} }
...@@ -5359,8 +5364,9 @@ public class Parser { ...@@ -5359,8 +5364,9 @@ 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) { boolean addViewToSession, boolean isPersistent, Session targetSession) {
Session targetSession = isPersistent ? database.getSystemSession() : session; //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();
...@@ -5372,7 +5378,7 @@ public class Parser { ...@@ -5372,7 +5378,7 @@ public class Parser {
synchronized(targetSession){ synchronized(targetSession){
view = new TableView(schema, id, cteViewName, querySQL, view = new TableView(schema, id, cteViewName, querySQL,
parameters, columnTemplateArray, targetSession, parameters, columnTemplateArray, targetSession,
allowRecursiveQueryDetection, false /* literalsChecked */); allowRecursiveQueryDetection, false /* literalsChecked */, true /* isTableExpression */);
if (!view.isRecursiveQueryDetected() && allowRecursiveQueryDetection) { if (!view.isRecursiveQueryDetected() && allowRecursiveQueryDetection) {
if(isPersistent){ if(isPersistent){
db.addSchemaObject(targetSession, view); db.addSchemaObject(targetSession, view);
...@@ -5383,7 +5389,7 @@ public class Parser { ...@@ -5383,7 +5389,7 @@ public class Parser {
} }
view = new TableView(schema, id, cteViewName, querySQL, parameters, view = new TableView(schema, id, cteViewName, querySQL, parameters,
columnTemplateArray, targetSession, columnTemplateArray, targetSession,
false/* assume recursive */, false /* literalsChecked */); false/* assume recursive */, false /* literalsChecked */, true /* isTableExpression */);
} }
} }
view.setTableExpression(true); view.setTableExpression(true);
...@@ -5405,6 +5411,7 @@ public class Parser { ...@@ -5405,6 +5411,7 @@ public class Parser {
private CreateView parseCreateView(boolean force, boolean orReplace) { private CreateView parseCreateView(boolean force, boolean orReplace) {
boolean ifNotExists = readIfNotExists(); boolean ifNotExists = readIfNotExists();
boolean isTableExpression = readIf("TABLE_EXPRESSION");
String viewName = readIdentifierWithSchema(); String viewName = readIdentifierWithSchema();
CreateView command = new CreateView(session, getSchema()); CreateView command = new CreateView(session, getSchema());
this.createView = command; this.createView = command;
...@@ -5413,6 +5420,7 @@ public class Parser { ...@@ -5413,6 +5420,7 @@ public class Parser {
command.setComment(readCommentIf()); command.setComment(readCommentIf());
command.setOrReplace(orReplace); command.setOrReplace(orReplace);
command.setForce(force); command.setForce(force);
command.setTableExpression(isTableExpression);
if (readIf("(")) { if (readIf("(")) {
String[] cols = parseColumnList(); String[] cols = parseColumnList();
command.setColumnNames(cols); command.setColumnNames(cols);
...@@ -5422,12 +5430,12 @@ public class Parser { ...@@ -5422,12 +5430,12 @@ public class Parser {
read("AS"); read("AS");
try { try {
Query query; Query query;
session.setParsingView(true); session.setParsingView(true,viewName);
try { try {
query = parseSelect(); query = parseSelect();
query.prepare(); query.prepare();
} finally { } finally {
session.setParsingView(false); session.setParsingView(false,viewName);
} }
command.setSelect(query); command.setSelect(query);
} catch (DbException e) { } catch (DbException e) {
......
...@@ -34,6 +34,7 @@ public class CreateView extends SchemaCommand { ...@@ -34,6 +34,7 @@ public class CreateView extends SchemaCommand {
private String comment; private String comment;
private boolean orReplace; private boolean orReplace;
private boolean force; private boolean force;
private boolean isTableExpression;
public CreateView(Session session, Schema schema) { public CreateView(Session session, Schema schema) {
super(session, schema); super(session, schema);
...@@ -71,6 +72,10 @@ public class CreateView extends SchemaCommand { ...@@ -71,6 +72,10 @@ public class CreateView extends SchemaCommand {
this.force = force; this.force = force;
} }
public void setTableExpression(boolean isTableExpression) {
this.isTableExpression=isTableExpression;
}
@Override @Override
public int update() { public int update() {
session.commit(true); session.commit(true);
...@@ -106,7 +111,7 @@ public class CreateView extends SchemaCommand { ...@@ -106,7 +111,7 @@ public class CreateView extends SchemaCommand {
} }
} }
if (view == null) { if (view == null) {
view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false, false); view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false, false, isTableExpression);
} else { } else {
view.replace(querySQL, columnTemplates, session, false, force, false); view.replace(querySQL, columnTemplates, session, false, force, false);
view.setModified(); view.setModified();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
package org.h2.command.ddl; package org.h2.command.ddl;
import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.constraint.ConstraintReferential; import org.h2.constraint.ConstraintReferential;
...@@ -68,6 +69,9 @@ public class DropView extends SchemaCommand { ...@@ -68,6 +69,9 @@ public class DropView extends SchemaCommand {
} }
} }
TableView tableView = (TableView) view;
ArrayList<Table> copyOfDependencies = new ArrayList<Table>(tableView.getTables());
// TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's // TODO: Where is the ConstraintReferential.CASCADE style drop processing ? It's
// supported from imported keys - but not for dependent db objects // supported from imported keys - but not for dependent db objects
...@@ -75,6 +79,18 @@ public class DropView extends SchemaCommand { ...@@ -75,6 +79,18 @@ public class DropView extends SchemaCommand {
session.getDatabase().removeSchemaObject(session, view); session.getDatabase().removeSchemaObject(session, view);
session.getDatabase().unlockMeta(session); session.getDatabase().unlockMeta(session);
session.getDatabase().flushDeferredRemoveSchemaObject(); session.getDatabase().flushDeferredRemoveSchemaObject();
// remove dependent table expressions
for( Table childTable: copyOfDependencies){
if(TableType.VIEW == childTable.getTableType()){
TableView childTableView = (TableView) childTable;
System.out.println("considering dep "+childTableView.getName());
if(childTableView.isTableExpression() && childTableView.getName()!=null){
System.out.println("removing "+childTableView.getName());
session.getDatabase().removeSchemaObject(session, childTableView);
}
}
}
} }
return 0; return 0;
} }
......
...@@ -1087,8 +1087,10 @@ public class Select extends Query { ...@@ -1087,8 +1087,10 @@ public class Select extends Query {
for (TableFilter f : topFilters) { for (TableFilter f : topFilters) {
Table t = f.getTable(); Table t = f.getTable();
boolean isPersistent = !t.isTemporary(); boolean isPersistent = !t.isTemporary();
System.out.println("topFilters[]="+t.getName());
if (t.isView() && ((TableView) t).isRecursive()) { if (t.isView() && ((TableView) t).isRecursive()) {
// hmmm - how do you generate a plan sql which is recursive
// for a system which does not natively support recursive SQLs... ?
// answer: you can't
TableView tv = ((TableView) t); TableView tv = ((TableView) t);
buff.append("WITH "); buff.append("WITH ");
if(tv.isRecursive()){ if(tv.isRecursive()){
......
...@@ -764,10 +764,12 @@ public class Database implements DataHandler { ...@@ -764,10 +764,12 @@ public class Database implements DataHandler {
MetaRecord rec = new MetaRecord(cursor.get()); MetaRecord rec = new MetaRecord(cursor.get());
objectIds.set(rec.getId()); objectIds.set(rec.getId());
records.add(rec); records.add(rec);
System.out.println("Loaded:"+rec.toString());
} }
Collections.sort(records); Collections.sort(records);
synchronized (systemSession) { synchronized (systemSession) {
for (MetaRecord rec : records) { for (MetaRecord rec : records) {
System.out.println("Executing:"+rec.toString());
rec.execute(this, systemSession, eventListener); rec.execute(this, systemSession, eventListener);
} }
} }
......
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
package org.h2.engine; package org.h2.engine;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Stack;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Command; import org.h2.command.Command;
...@@ -121,6 +123,7 @@ public class Session extends SessionWithState { ...@@ -121,6 +123,7 @@ public class Session extends SessionWithState {
private long modificationMetaID = -1; private long modificationMetaID = -1;
private SubQueryInfo subQueryInfo; private SubQueryInfo subQueryInfo;
private int parsingView; private int parsingView;
private Stack<String> viewNameStack = new Stack<String>();
private int preparingQueryExpression; private int preparingQueryExpression;
private volatile SmallLRUCache<Object, ViewIndex> viewIndexCache; private volatile SmallLRUCache<Object, ViewIndex> viewIndexCache;
private HashMap<Object, ViewIndex> subQueryIndexCache; private HashMap<Object, ViewIndex> subQueryIndexCache;
...@@ -226,10 +229,25 @@ public class Session extends SessionWithState { ...@@ -226,10 +229,25 @@ public class Session extends SessionWithState {
return subQueryInfo; return subQueryInfo;
} }
public void setParsingView(boolean parsingView) { public void setParsingView(boolean parsingView, String viewName) {
// It can be recursive, thus implemented as counter. // It can be recursive, thus implemented as counter.
this.parsingView += parsingView ? 1 : -1; this.parsingView += parsingView ? 1 : -1;
assert this.parsingView >= 0; assert this.parsingView >= 0;
if(parsingView){
viewNameStack.push(viewName);
}else
{
assert viewName.equals(viewNameStack.peek());
viewNameStack.pop();
}
}
public String getParsingViewName() {
try{
return viewNameStack.peek();
}
catch(EmptyStackException e){
return null;
}
} }
public boolean isParsingView() { public boolean isParsingView() {
......
...@@ -8,6 +8,7 @@ package org.h2.table; ...@@ -8,6 +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;
...@@ -58,13 +59,14 @@ public class TableView extends Table { ...@@ -58,13 +59,14 @@ public class TableView extends Table {
private Query topQuery; private Query topQuery;
private ResultInterface recursiveResult; private ResultInterface recursiveResult;
private boolean isRecursiveQueryDetected; private boolean isRecursiveQueryDetected;
private boolean isTableExpression;
// private Session session; // private Session session;
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 recursive, boolean literalsChecked, boolean isTableExpression) {
super(schema, id, name, false, true); super(schema, id, name, false, true);
init(querySQL, params, columnTemplates, session, recursive, literalsChecked); init(querySQL, params, columnTemplates, session, recursive, literalsChecked, isTableExpression);
} }
/** /**
...@@ -84,33 +86,35 @@ public class TableView extends Table { ...@@ -84,33 +86,35 @@ public class TableView extends Table {
init(querySQL, null, init(querySQL, null,
newColumnTemplates == null ? this.columnTemplates newColumnTemplates == null ? this.columnTemplates
: newColumnTemplates, : newColumnTemplates,
session, recursive, literalsChecked); session, recursive, literalsChecked, isTableExpression);
DbException e = recompile(session, force, true); DbException e = recompile(session, force, true);
if (e != null) { if (e != null) {
init(oldQuerySQL, null, oldColumnTemplates, session, oldRecursive, literalsChecked); init(oldQuerySQL, null, oldColumnTemplates, session, oldRecursive,
literalsChecked, isTableExpression);
recompile(session, true, false); recompile(session, true, false);
throw e; throw e;
} }
} }
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) { Column[] columnTemplates, Session session, boolean recursive, boolean literalsChecked, boolean isTableExpression) {
this.querySQL = querySQL; this.querySQL = querySQL;
this.columnTemplates = columnTemplates; this.columnTemplates = columnTemplates;
this.recursive = recursive; this.recursive = recursive;
this.isRecursiveQueryDetected = false; this.isRecursiveQueryDetected = false;
this.isTableExpression = isTableExpression;
//this.session = session; //this.session = session;
index = new ViewIndex(this, querySQL, params, recursive); index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session, literalsChecked); initColumnsAndTables(session, literalsChecked);
} }
private static Query compileViewQuery(Session session, String sql, boolean literalsChecked) { private static Query compileViewQuery(Session session, String sql, boolean literalsChecked, String viewName) {
Prepared p; Prepared p;
session.setParsingView(true); session.setParsingView(true,viewName);
try { try {
p = session.prepare(sql, false, literalsChecked); p = session.prepare(sql, false, literalsChecked);
} finally { } finally {
session.setParsingView(false); session.setParsingView(false,viewName);
} }
if (!(p instanceof Query)) { if (!(p instanceof Query)) {
throw DbException.getSyntaxError(sql, 0); throw DbException.getSyntaxError(sql, 0);
...@@ -130,7 +134,7 @@ public class TableView extends Table { ...@@ -130,7 +134,7 @@ public class TableView extends Table {
public synchronized DbException recompile(Session session, boolean force, public synchronized DbException recompile(Session session, boolean force,
boolean clearIndexCache) { boolean clearIndexCache) {
try { try {
compileViewQuery(session, querySQL, false); compileViewQuery(session, querySQL, false, getName());
} catch (DbException e) { } catch (DbException e) {
if (!force) { if (!force) {
return e; return e;
...@@ -153,13 +157,14 @@ public class TableView extends Table { ...@@ -153,13 +157,14 @@ public class TableView extends Table {
private void initColumnsAndTables(Session session, boolean literalsChecked) { private void initColumnsAndTables(Session session, boolean literalsChecked) {
Column[] cols; Column[] cols;
removeDependentViewFromTables(); removeDependentViewFromTables();
setTableExpression(isTableExpression);
try { try {
Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked); Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked, getName());
this.querySQL = compiledQuery.getPlanSQL(); this.querySQL = compiledQuery.getPlanSQL();
tables = New.arrayList(compiledQuery.getTables()); tables = New.arrayList(compiledQuery.getTables());
ArrayList<Expression> expressions = compiledQuery.getExpressions(); ArrayList<Expression> expressions = compiledQuery.getExpressions();
ArrayList<Column> list = New.arrayList(); ArrayList<Column> list = New.arrayList();
ColumnNamer columnNamer= new ColumnNamer(session); ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0, count = compiledQuery.getColumnCount(); i < count; i++) { for (int i = 0, count = compiledQuery.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i); Expression expr = expressions.get(i);
String name = null; String name = null;
...@@ -320,6 +325,9 @@ public class TableView extends Table { ...@@ -320,6 +325,9 @@ public class TableView extends Table {
buff.append("FORCE "); buff.append("FORCE ");
} }
buff.append("VIEW "); buff.append("VIEW ");
if (isTableExpression) {
buff.append("TABLE_EXPRESSION ");
}
buff.append(quotedName); buff.append(quotedName);
if (comment != null) { if (comment != null) {
buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment)); buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(comment));
...@@ -541,7 +549,7 @@ public class TableView extends Table { ...@@ -541,7 +549,7 @@ public class TableView extends Table {
String querySQL = query.getPlanSQL(); String querySQL = query.getPlanSQL();
TableView v = new TableView(mainSchema, 0, name, TableView v = new TableView(mainSchema, 0, name,
querySQL, query.getParameters(), null, session, querySQL, query.getParameters(), null, session,
false, true /* literals have already been checked when parsing original query */); false, true /* literals have already been checked when parsing original query */, false);
if (v.createException != null) { if (v.createException != null) {
throw v.createException; throw v.createException;
} }
...@@ -691,6 +699,10 @@ public class TableView extends Table { ...@@ -691,6 +699,10 @@ public class TableView extends Table {
return true; return true;
} }
public List<Table> getTables(){
return tables;
}
// @Override // @Override
// public void removeView(TableView view){ // public void removeView(TableView view){
// super.removeView(view); // super.removeView(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");
...@@ -622,7 +622,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -622,7 +622,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
for(int queryRunTries=1;queryRunTries<=maxRetries;queryRunTries++){ for(int queryRunTries=1;queryRunTries<=maxRetries;queryRunTries++){
System.out.println("Iteration #"+queryRunTries); System.out.println("==================================== Iteration #"+queryRunTries);
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute(SETUP_SQL); stat.execute(SETUP_SQL);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论