提交 5a2c152e authored 作者: Thomas Mueller's avatar Thomas Mueller

Linked tables that point to the same database now share the connection.

上级 272423cb
...@@ -49,6 +49,7 @@ import org.h2.table.IndexColumn; ...@@ -49,6 +49,7 @@ import org.h2.table.IndexColumn;
import org.h2.table.MetaTable; import org.h2.table.MetaTable;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.table.TableData; import org.h2.table.TableData;
import org.h2.table.TableLinkConnection;
import org.h2.table.TableView; import org.h2.table.TableView;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server; import org.h2.tools.Server;
...@@ -160,6 +161,7 @@ public class Database implements DataHandler { ...@@ -160,6 +161,7 @@ public class Database implements DataHandler {
private boolean autoServerMode; private boolean autoServerMode;
private Object reserveMemory; private Object reserveMemory;
private Server server; private Server server;
private HashMap linkConnections;
public Database(String name, ConnectionInfo ci, String cipher) throws SQLException { public Database(String name, ConnectionInfo ci, String cipher) throws SQLException {
this.compareMode = new CompareMode(null, null, 0); this.compareMode = new CompareMode(null, null, 0);
...@@ -2054,4 +2056,20 @@ public class Database implements DataHandler { ...@@ -2054,4 +2056,20 @@ public class Database implements DataHandler {
reserveMemory = null; reserveMemory = null;
} }
/**
* Open a new connection or get an existing connection to another database.
*
* @param driver the database driver or null
* @param url the database URL
* @param user the user name
* @param password the password
* @return the connection
*/
public TableLinkConnection getLinkConnection(String driver, String url, String user, String password) throws SQLException {
if (linkConnections == null) {
linkConnections = new HashMap();
}
return TableLinkConnection.open(linkConnections, driver, url, user, password);
}
} }
...@@ -67,6 +67,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -67,6 +67,7 @@ public class LinkedIndex extends BaseIndex {
} }
buff.append(')'); buff.append(')');
String sql = buff.toString(); String sql = buff.toString();
synchronized (link.getConnection()) {
try { try {
PreparedStatement prep = link.getPreparedStatement(sql); PreparedStatement prep = link.getPreparedStatement(sql);
for (int i = 0, j = 0; i < row.getColumnCount(); i++) { for (int i = 0, j = 0; i < row.getColumnCount(); i++) {
...@@ -82,6 +83,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -82,6 +83,7 @@ public class LinkedIndex extends BaseIndex {
throw wrapException(sql, e); throw wrapException(sql, e);
} }
} }
}
public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException { public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
...@@ -114,6 +116,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -114,6 +116,7 @@ public class LinkedIndex extends BaseIndex {
} }
buff.insert(0, "SELECT * FROM " + targetTableName + " T"); buff.insert(0, "SELECT * FROM " + targetTableName + " T");
String sql = buff.toString(); String sql = buff.toString();
synchronized (link.getConnection()) {
try { try {
PreparedStatement prep = link.getPreparedStatement(sql); PreparedStatement prep = link.getPreparedStatement(sql);
int j = 0; int j = 0;
...@@ -137,6 +140,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -137,6 +140,7 @@ public class LinkedIndex extends BaseIndex {
throw wrapException(sql, e); throw wrapException(sql, e);
} }
} }
}
private void addParameter(StringBuffer buff, Column col) { private void addParameter(StringBuffer buff, Column col) {
if (col.getType() == Value.STRING_FIXED && link.isOracle()) { if (col.getType() == Value.STRING_FIXED && link.isOracle()) {
...@@ -202,6 +206,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -202,6 +206,7 @@ public class LinkedIndex extends BaseIndex {
} }
} }
String sql = buff.toString(); String sql = buff.toString();
synchronized (link.getConnection()) {
try { try {
PreparedStatement prep = link.getPreparedStatement(sql); PreparedStatement prep = link.getPreparedStatement(sql);
for (int i = 0, j = 0; i < row.getColumnCount(); i++) { for (int i = 0, j = 0; i < row.getColumnCount(); i++) {
...@@ -217,6 +222,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -217,6 +222,7 @@ public class LinkedIndex extends BaseIndex {
throw wrapException(sql, e); throw wrapException(sql, e);
} }
} }
}
/** /**
* Update a row using a UPDATE statement. This method is to be called if the * Update a row using a UPDATE statement. This method is to be called if the
...@@ -251,6 +257,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -251,6 +257,7 @@ public class LinkedIndex extends BaseIndex {
} }
} }
String sql = buff.toString(); String sql = buff.toString();
synchronized (link.getConnection()) {
try { try {
int j = 1; int j = 1;
PreparedStatement prep = link.getPreparedStatement(sql); PreparedStatement prep = link.getPreparedStatement(sql);
...@@ -272,6 +279,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -272,6 +279,7 @@ public class LinkedIndex extends BaseIndex {
throw wrapException(sql, e); throw wrapException(sql, e);
} }
} }
}
private SQLException wrapException(String sql, SQLException e) { private SQLException wrapException(String sql, SQLException e) {
return Message.getSQLException(ErrorCode.ERROR_ACCESSING_LINKED_TABLE_2, new String[] { sql, e.toString() }, e); return Message.getSQLException(ErrorCode.ERROR_ACCESSING_LINKED_TABLE_2, new String[] { sql, e.toString() }, e);
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
package org.h2.table; package org.h2.table;
import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -40,7 +39,7 @@ import org.h2.value.DataType; ...@@ -40,7 +39,7 @@ import org.h2.value.DataType;
public class TableLink extends Table { public class TableLink extends Table {
private String driver, url, user, password, originalSchema, originalTable, qualifiedTableName; private String driver, url, user, password, originalSchema, originalTable, qualifiedTableName;
private Connection conn; private TableLinkConnection conn;
private HashMap prepared = new HashMap(); private HashMap prepared = new HashMap();
private final ObjectArray indexes = new ObjectArray(); private final ObjectArray indexes = new ObjectArray();
private final boolean emitUpdates; private final boolean emitUpdates;
...@@ -77,8 +76,20 @@ public class TableLink extends Table { ...@@ -77,8 +76,20 @@ public class TableLink extends Table {
} }
private void connect() throws SQLException { private void connect() throws SQLException {
conn = JdbcUtils.getConnection(driver, url, user, password); conn = database.getLinkConnection(driver, url, user, password);
DatabaseMetaData meta = conn.getMetaData(); synchronized (conn) {
try {
readMetaData();
} catch (SQLException e) {
conn.close();
conn = null;
throw e;
}
}
}
private void readMetaData() throws SQLException {
DatabaseMetaData meta = conn.getConnection().getMetaData();
storesLowerCase = meta.storesLowerCaseIdentifiers(); storesLowerCase = meta.storesLowerCaseIdentifiers();
storesMixedCase = meta.storesMixedCaseIdentifiers(); storesMixedCase = meta.storesMixedCaseIdentifiers();
supportsMixedCaseIdentifiers = meta.supportsMixedCaseIdentifiers(); supportsMixedCaseIdentifiers = meta.supportsMixedCaseIdentifiers();
...@@ -129,7 +140,7 @@ public class TableLink extends Table { ...@@ -129,7 +140,7 @@ public class TableLink extends Table {
// check if the table is accessible // check if the table is accessible
Statement stat = null; Statement stat = null;
try { try {
stat = conn.createStatement(); stat = conn.getConnection().createStatement();
rs = stat.executeQuery("SELECT * FROM " + qualifiedTableName + " T WHERE 1=0"); rs = stat.executeQuery("SELECT * FROM " + qualifiedTableName + " T WHERE 1=0");
if (columnList.size() == 0) { if (columnList.size() == 0) {
// alternative solution // alternative solution
...@@ -359,7 +370,7 @@ public class TableLink extends Table { ...@@ -359,7 +370,7 @@ public class TableLink extends Table {
} }
PreparedStatement prep = (PreparedStatement) prepared.get(sql); PreparedStatement prep = (PreparedStatement) prepared.get(sql);
if (prep == null) { if (prep == null) {
prep = conn.prepareStatement(sql); prep = conn.getConnection().prepareStatement(sql);
prepared.put(sql, prep); prepared.put(sql, prep);
} }
return prep; return prep;
...@@ -399,7 +410,6 @@ public class TableLink extends Table { ...@@ -399,7 +410,6 @@ public class TableLink extends Table {
database.removeMeta(session, getId()); database.removeMeta(session, getId());
driver = null; driver = null;
url = user = password = originalTable = null; url = user = password = originalTable = null;
conn = null;
prepared = null; prepared = null;
invalidate(); invalidate();
} }
...@@ -457,4 +467,8 @@ public class TableLink extends Table { ...@@ -457,4 +467,8 @@ public class TableLink extends Table {
this.readOnly = readOnly; this.readOnly = readOnly;
} }
public TableLinkConnection getConnection() {
return conn;
}
} }
...@@ -195,4 +195,14 @@ public class ObjectUtils { ...@@ -195,4 +195,14 @@ public class ObjectUtils {
} }
} }
/**
* Calculate the hash code of the given object. The object may be null.
*
* @param the object
* @return the hash code, or 0 if the object is null
*/
public static int hashCode(Object o) {
return o == null ? 0 : o.hashCode();
}
} }
...@@ -276,8 +276,6 @@ java org.h2.test.TestAll timer ...@@ -276,8 +276,6 @@ java org.h2.test.TestAll timer
test on linux test on linux
main methods for the tests and make that work
TestMVCC: TestMVCC:
Concurrent update in table test: another transaction has updated or Concurrent update in table test: another transaction has updated or
deleted the same row when exactly does it occur in other databases deleted the same row when exactly does it occur in other databases
......
...@@ -41,7 +41,7 @@ public abstract class TestBase { ...@@ -41,7 +41,7 @@ public abstract class TestBase {
*/ */
protected TestAll config; protected TestAll config;
private long start; protected long start;
/** /**
* Get the test directory for this test. * Get the test directory for this test.
......
...@@ -73,6 +73,7 @@ public class TestLinkedTable extends TestBase { ...@@ -73,6 +73,7 @@ public class TestLinkedTable extends TestBase {
sa.execute("CREATE SCHEMA P"); sa.execute("CREATE SCHEMA P");
sa.execute("CREATE TABLE P.TEST(X INT)"); sa.execute("CREATE TABLE P.TEST(X INT)");
sa.execute("INSERT INTO TEST VALUES(1)"); sa.execute("INSERT INTO TEST VALUES(1)");
sa.execute("INSERT INTO P.TEST VALUES(2)");
try { try {
sb.execute("CREATE LINKED TABLE T(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'TEST')"); sb.execute("CREATE LINKED TABLE T(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'TEST')");
fail(); fail();
...@@ -81,6 +82,8 @@ public class TestLinkedTable extends TestBase { ...@@ -81,6 +82,8 @@ public class TestLinkedTable extends TestBase {
} }
sb.execute("CREATE LINKED TABLE T(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'PUBLIC', 'TEST')"); sb.execute("CREATE LINKED TABLE T(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'PUBLIC', 'TEST')");
sb.execute("CREATE LINKED TABLE T2(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'P', 'TEST')"); sb.execute("CREATE LINKED TABLE T2(NULL, 'jdbc:h2:mem:one', 'sa', 'sa', 'P', 'TEST')");
assertSingleValue(sb, "SELECT * FROM T", 1);
assertSingleValue(sb, "SELECT * FROM T2", 2);
sa.execute("DROP ALL OBJECTS"); sa.execute("DROP ALL OBJECTS");
sb.execute("DROP ALL OBJECTS"); sb.execute("DROP ALL OBJECTS");
ca.close(); ca.close();
......
...@@ -21,7 +21,7 @@ import org.h2.util.JdbcUtils; ...@@ -21,7 +21,7 @@ import org.h2.util.JdbcUtils;
*/ */
public class TestListener extends TestBase implements DatabaseEventListener { public class TestListener extends TestBase implements DatabaseEventListener {
private long last, start; private long last;
private int lastState = -1; private int lastState = -1;
private String url; private String url;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论