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

Got database loading working for non recursive table expressions

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