提交 c2b4d9db authored 作者: Noel Grandin's avatar Noel Grandin

fix concurrent access to views array in Table

as a consequence of my previous change to create views on the current session instead of the system session
上级 efee13cf
......@@ -8,6 +8,7 @@ package org.h2.command.ddl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.command.Parser;
......@@ -274,9 +275,8 @@ public class AlterTableAlterColumn extends SchemaCommand {
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, e, getSQL(), e.getMessage());
}
String tableName = table.getName();
ArrayList<TableView> views = table.getViews();
CopyOnWriteArrayList<TableView> views = table.getViews();
if (views != null) {
views = New.arrayList(views);
for (TableView view : views) {
table.removeView(view);
}
......
......@@ -5,8 +5,7 @@
*/
package org.h2.command.ddl;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.constraint.ConstraintReferential;
......@@ -74,7 +73,7 @@ public class DropTable extends SchemaCommand {
throw DbException.get(ErrorCode.CANNOT_DROP_TABLE_1, tableName);
}
if (dropAction == ConstraintReferential.RESTRICT) {
ArrayList<TableView> views = table.getViews();
CopyOnWriteArrayList<TableView> views = table.getViews();
if (views != null && views.size() > 0) {
StatementBuilder buff = new StatementBuilder();
for (TableView v : views) {
......
......@@ -10,6 +10,8 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.constraint.Constraint;
......@@ -77,7 +79,7 @@ public abstract class Table extends SchemaObjectBase {
private ArrayList<TriggerObject> triggers;
private ArrayList<Constraint> constraints;
private ArrayList<Sequence> sequences;
private ArrayList<TableView> views;
private AtomicReference<CopyOnWriteArrayList<TableView>> views;
private ArrayList<TableSynonym> synonyms;
private boolean checkForeignKeyConstraints = true;
private boolean onCommitDrop, onCommitTruncate;
......@@ -398,8 +400,8 @@ public abstract class Table extends SchemaObjectBase {
if (sequences != null) {
children.addAll(sequences);
}
if (views != null) {
children.addAll(views);
if (views.get() != null) {
children.addAll(views.get());
}
if (synonyms != null) {
children.addAll(synonyms);
......@@ -519,15 +521,15 @@ public abstract class Table extends SchemaObjectBase {
}
}
public ArrayList<TableView> getViews() {
return views;
public CopyOnWriteArrayList<TableView> getViews() {
return views.get();
}
@Override
public void removeChildrenAndResources(Session session) {
while (views != null && views.size() > 0) {
TableView view = views.get(0);
views.remove(0);
while (views.get() != null && views.get().size() > 0) {
TableView view = views.get().get(0);
views.get().remove(0);
database.removeSchemaObject(session, view);
}
while (synonyms != null && synonyms.size() > 0) {
......@@ -811,10 +813,13 @@ public abstract class Table extends SchemaObjectBase {
private static void remove(ArrayList<? extends DbObject> list, DbObject obj) {
if (list != null) {
int i = list.indexOf(obj);
if (i >= 0) {
list.remove(i);
}
list.remove(obj);
}
}
private static <T> void remove(AtomicReference<CopyOnWriteArrayList<T>> list, T obj) {
if (list.get() != null) {
list.get().remove(obj);
}
}
......@@ -886,7 +891,7 @@ public abstract class Table extends SchemaObjectBase {
* @param view the view to add
*/
public void addView(TableView view) {
views = add(views, view);
add(views, view);
}
/**
......@@ -940,6 +945,14 @@ public abstract class Table extends SchemaObjectBase {
return list;
}
private static <T> void add(AtomicReference<CopyOnWriteArrayList<T>> list, T obj) {
if (list.get() == null) {
list.compareAndSet(null, new CopyOnWriteArrayList<T>());
}
// self constraints are two entries in the list
list.get().add(obj);
}
/**
* Fire the triggers for this table.
*
......
......@@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.command.dml.Query;
......@@ -135,10 +136,7 @@ public class TableView extends Table {
return e;
}
}
ArrayList<TableView> views = getViews();
if (views != null) {
views = New.arrayList(views);
}
CopyOnWriteArrayList<TableView> views = getViews();
initColumnsAndTables(session, false);
if (views != null) {
for (TableView v : views) {
......@@ -163,7 +161,7 @@ public class TableView extends Table {
tables = New.arrayList(query.getTables());
ArrayList<Expression> expressions = query.getExpressions();
ArrayList<Column> list = New.arrayList();
ColumnNamer columnNamer= new ColumnNamer(session);
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0, count = query.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i);
String name = null;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论