提交 180841cb authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 778946d4
#Fri Nov 09 12:31:47 CET 2007 #Mon Nov 19 20:09:20 CET 2007
benchmark.drivers.dir=C\:/data/java
javac=javac javac=javac
benchmark.drivers.dir=C\:/data/java
path.servlet.jar=C\:/data/classpath/servlet-api.jar path.servlet.jar=C\:/data/classpath/servlet-api.jar
path.lucene.jar=C\:/data/classpath/lucene-core-2.2.0.jar
version.name.maven=1.0.61 version.name.maven=1.0.61
path.lucene.jar=C\:/data/classpath/lucene-core-2.2.0.jar
jdk=1.4 jdk=1.4
...@@ -50,12 +50,21 @@ ...@@ -50,12 +50,21 @@
<javac executable="${javac}" srcdir="src/tools" destdir="bin" debug="true" includes="org/h2/tools/code/CodeSwitch.java"/> <javac executable="${javac}" srcdir="src/tools" destdir="bin" debug="true" includes="org/h2/tools/code/CodeSwitch.java"/>
</target> </target>
<target name="codeswitchAndroid" depends="codeswitchPrepare">
<propertyfile file="ant-build.properties">
<entry key="jdk" value="1.3" />
</propertyfile>
<java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin">
<arg line="+JDK13 -JDK14 -JDK16 -AWT ../src/main/org/h2"/>
</java>
</target>
<target name="codeswitchJdk13" depends="codeswitchPrepare"> <target name="codeswitchJdk13" depends="codeswitchPrepare">
<propertyfile file="ant-build.properties"> <propertyfile file="ant-build.properties">
<entry key="jdk" value="1.3" /> <entry key="jdk" value="1.3" />
</propertyfile> </propertyfile>
<java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin"> <java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin">
<arg line="+JDK13 -JDK14 -JDK16 ../src/main/org/h2"/> <arg line="+JDK13 -JDK14 -JDK16 +AWT ../src/main/org/h2"/>
</java> </java>
</target> </target>
...@@ -64,7 +73,7 @@ ...@@ -64,7 +73,7 @@
<entry key="jdk" value="1.4" /> <entry key="jdk" value="1.4" />
</propertyfile> </propertyfile>
<java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin"> <java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin">
<arg line="-JDK13 +JDK14 -JDK16 ../src/main/org/h2"/> <arg line="-JDK13 +JDK14 -JDK16 +AWT ../src/main/org/h2"/>
</java> </java>
</target> </target>
...@@ -73,7 +82,7 @@ ...@@ -73,7 +82,7 @@
<entry key="jdk" value="1.6" /> <entry key="jdk" value="1.6" />
</propertyfile> </propertyfile>
<java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin"> <java classname="org.h2.tools.code.CodeSwitch" fork="true" dir="bin">
<arg line="-JDK13 +JDK16 +JDK14 ../src/main/org/h2"/> <arg line="-JDK13 +JDK14 +JDK16 +AWT ../src/main/org/h2"/>
</java> </java>
</target> </target>
......
...@@ -155,12 +155,8 @@ However, the startup of the GCJ version is faster than when using a VM. ...@@ -155,12 +155,8 @@ However, the startup of the GCJ version is faster than when using a VM.
<br /><a name="translate"></a> <br /><a name="translate"></a>
<h3>How to Translate this Project?</h3> <h3>How to Translate this Project?</h3>
<p> <p>
The following files can be translated at the moment: For more information, see
<pre> <a href="build.html#translating">Build/Translating</a>.
src/main/org/h2/server/web/res/_text_*.properties
src/main/org/h2/res/_messages_*.properties
src/docsrc/text/_docs_*.utf8.txt
</pre>
</p> </p>
</div></td></tr></table></body></html> </div></td></tr></table></body></html>
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package org.h2.fulltext; package org.h2.fulltext;
//#ifdef JDK14
import java.io.IOException; import java.io.IOException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
...@@ -33,26 +34,33 @@ import org.h2.store.fs.FileSystem; ...@@ -33,26 +34,33 @@ import org.h2.store.fs.FileSystem;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
//#endif
/** /**
* This class implements the full text search based on Apache Lucene. * This class implements the full text search based on Apache Lucene.
*/ */
public class FullTextLucene implements Trigger { public class FullTextLucene
//#ifdef JDK14
implements Trigger
//#endif
{
//#ifdef JDK14
private static HashMap indexers = new HashMap(); private static HashMap indexers = new HashMap();
private static final String FIELD_DATA = "data"; private static final String FIELD_DATA = "data";
private static final String FIELD_QUERY = "query"; private static final String FIELD_QUERY = "query";
private static final String FIELD_COLUMN_PREFIX = "_"; private static final String FIELD_COLUMN_PREFIX = "_";
private static final String TRIGGER_PREFIX = "FTL_"; private static final String TRIGGER_PREFIX = "FTL_";
private static final String SCHEMA = "FTL"; private static final String SCHEMA = "FTL";
private IndexModifier indexer;
private String schemaName; private String schemaName;
private String tableName; private String tableName;
private int[] keys; private int[] keys;
private int[] indexColumns; private int[] indexColumns;
private String[] columnNames; private String[] columnNames;
private int[] dataTypes; private int[] dataTypes;
private IndexModifier indexer;
//#endif
/** /**
* Create a new full text index for a table and column list. Each table may only have one index at any time. * Create a new full text index for a table and column list. Each table may only have one index at any time.
* *
...@@ -62,6 +70,7 @@ public class FullTextLucene implements Trigger { ...@@ -62,6 +70,7 @@ public class FullTextLucene implements Trigger {
* @param table the table name * @param table the table name
* @param columnList the column list (null for all columns) * @param columnList the column list (null for all columns)
*/ */
//#ifdef JDK14
public static void createIndex(Connection conn, String schema, String table, String columnList) throws SQLException { public static void createIndex(Connection conn, String schema, String table, String columnList) throws SQLException {
init(conn); init(conn);
PreparedStatement prep = conn.prepareStatement("INSERT INTO "+SCHEMA+".INDEXES(SCHEMA, TABLE, COLUMNS) VALUES(?, ?, ?)"); PreparedStatement prep = conn.prepareStatement("INSERT INTO "+SCHEMA+".INDEXES(SCHEMA, TABLE, COLUMNS) VALUES(?, ?, ?)");
...@@ -72,42 +81,14 @@ public class FullTextLucene implements Trigger { ...@@ -72,42 +81,14 @@ public class FullTextLucene implements Trigger {
createTrigger(conn, schema, table); createTrigger(conn, schema, table);
indexExistingRows(conn, schema, table); indexExistingRows(conn, schema, table);
} }
//#endif
private static void createTrigger(Connection conn, String schema, String table) throws SQLException {
Statement stat = conn.createStatement();
String trigger = StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(TRIGGER_PREFIX + table);
stat.execute("DROP TRIGGER IF EXISTS " + trigger);
StringBuffer buff = new StringBuffer("CREATE TRIGGER IF NOT EXISTS ");
buff.append(trigger);
buff.append(" AFTER INSERT, UPDATE, DELETE ON ");
buff.append(StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(table));
buff.append(" FOR EACH ROW CALL \"");
buff.append(FullTextLucene.class.getName());
buff.append("\"");
stat.execute(buff.toString());
}
private static void indexExistingRows(Connection conn, String schema, String table) throws SQLException {
FullTextLucene existing = new FullTextLucene();
existing.init(conn, schema, null, table);
StringBuffer buff = new StringBuffer("SELECT * FROM ");
buff.append(StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(table));
ResultSet rs = conn.createStatement().executeQuery(buff.toString());
int columnCount = rs.getMetaData().getColumnCount();
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 0; i < columnCount; i++) {
row[i] = rs.getObject(i + 1);
}
existing.fire(conn, null, row);
}
}
/** /**
* Re-creates the full text index for this database * Re-creates the full text index for this database
* *
* @param conn the connection * @param conn the connection
*/ */
//#ifdef JDK14
public static void reindex(Connection conn) throws SQLException { public static void reindex(Connection conn) throws SQLException {
init(conn); init(conn);
removeAllTriggers(conn); removeAllTriggers(conn);
...@@ -121,47 +102,21 @@ public class FullTextLucene implements Trigger { ...@@ -121,47 +102,21 @@ public class FullTextLucene implements Trigger {
indexExistingRows(conn, schema, table); indexExistingRows(conn, schema, table);
} }
} }
//#endif
private static void removeAllTriggers(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TRIGGERS");
Statement stat2 = conn.createStatement();
while (rs.next()) {
String schema = rs.getString("TRIGGER_SCHEMA");
String name = rs.getString("TRIGGER_NAME");
if (name.startsWith(TRIGGER_PREFIX)) {
name = StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(name);
stat2.execute("DROP TRIGGER " + name);
}
}
}
private static void removeIndexFiles(Connection conn) throws SQLException {
String path = getIndexPath(conn);
IndexModifier index = (IndexModifier) indexers.get(path);
if (index != null) {
indexers.remove(path);
try {
index.flush();
index.close();
} catch (IOException e) {
throw convertException(e);
}
}
FileSystem.getInstance(path).deleteRecursive(path);
}
/** /**
* Drops all full text indexes from the database. * Drops all full text indexes from the database.
* *
* @param conn the connection * @param conn the connection
*/ */
//#ifdef JDK14
public static void dropAll(Connection conn) throws SQLException { public static void dropAll(Connection conn) throws SQLException {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA); stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA);
removeAllTriggers(conn); removeAllTriggers(conn);
removeIndexFiles(conn); removeIndexFiles(conn);
} }
//#endif
/** /**
* Initializes full text search functionality for this database. This adds the following Java functions to the * Initializes full text search functionality for this database. This adds the following Java functions to the
...@@ -182,6 +137,7 @@ public class FullTextLucene implements Trigger { ...@@ -182,6 +137,7 @@ public class FullTextLucene implements Trigger {
* *
* @param conn * @param conn
*/ */
//#ifdef JDK14
public static void init(Connection conn) throws SQLException { public static void init(Connection conn) throws SQLException {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("CREATE SCHEMA IF NOT EXISTS " + SCHEMA); stat.execute("CREATE SCHEMA IF NOT EXISTS " + SCHEMA);
...@@ -191,40 +147,12 @@ public class FullTextLucene implements Trigger { ...@@ -191,40 +147,12 @@ public class FullTextLucene implements Trigger {
stat.execute("CREATE ALIAS IF NOT EXISTS FTL_REINDEX FOR \"" + FullTextLucene.class.getName() + ".reindex\""); stat.execute("CREATE ALIAS IF NOT EXISTS FTL_REINDEX FOR \"" + FullTextLucene.class.getName() + ".reindex\"");
stat.execute("CREATE ALIAS IF NOT EXISTS FTL_DROP_ALL FOR \"" + FullTextLucene.class.getName() + ".dropAll\""); stat.execute("CREATE ALIAS IF NOT EXISTS FTL_DROP_ALL FOR \"" + FullTextLucene.class.getName() + ".dropAll\"");
} }
//#endif
private static IndexModifier getIndexModifier(Connection conn) throws SQLException {
try {
String path = getIndexPath(conn);
IndexModifier indexer;
synchronized (indexers) {
indexer = (IndexModifier) indexers.get(path);
if (indexer == null) {
// TODO: create flag = true means re-create
indexer = new IndexModifier(path, new StandardAnalyzer(), true);
indexers.put(path, indexer);
}
}
return indexer;
} catch (IOException e) {
throw convertException(e);
}
}
private static String getIndexPath(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("CALL DATABASE_PATH()");
rs.next();
String path = rs.getString(1);
if (path == null) {
throw new SQLException("FULLTEXT", "Fulltext search for in-memory databases is not supported.");
}
rs.close();
return path;
}
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef JDK14
public void init(Connection conn, String schemaName, String triggerName, String tableName) throws SQLException { public void init(Connection conn, String schemaName, String triggerName, String tableName) throws SQLException {
init(conn); init(conn);
this.schemaName = schemaName; this.schemaName = schemaName;
...@@ -275,27 +203,12 @@ public class FullTextLucene implements Trigger { ...@@ -275,27 +203,12 @@ public class FullTextLucene implements Trigger {
indexColumns = new int[indexList.size()]; indexColumns = new int[indexList.size()];
setColumns(indexColumns, indexList, columnList); setColumns(indexColumns, indexList, columnList);
} }
//#endif
private void setColumns(int[] index, ArrayList keys, ArrayList columns) throws SQLException {
for (int i = 0; i < keys.size(); i++) {
String key = (String) keys.get(i);
int found = -1;
for (int j = 0; found == -1 && j < columns.size(); j++) {
String column = (String) columns.get(j);
if (column.equals(key)) {
found = j;
}
}
if (found < 0) {
throw new SQLException("FULLTEXT", "Column not found: " + key);
}
index[i] = found;
}
}
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef JDK14
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException { public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
if (oldRow != null) { if (oldRow != null) {
delete(oldRow); delete(oldRow);
...@@ -304,7 +217,81 @@ public class FullTextLucene implements Trigger { ...@@ -304,7 +217,81 @@ public class FullTextLucene implements Trigger {
insert(newRow); insert(newRow);
} }
} }
//#endif
/**
* Searches from the full text index for this database.
*
* @param conn the connection
* @param text the search query
* @param limit the maximum number of rows or 0 for no limit
* @param offset the offset or 0 for no offset
* @return the result set
*/
//#ifdef JDK14
public static ResultSet search(Connection conn, String text, int limit, int offset) throws SQLException {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn(FIELD_QUERY, Types.VARCHAR, 0, 0);
if (text == null) {
// this is just to query the result set columns
return rs;
}
String path = getIndexPath(conn);
try {
IndexModifier indexer = getIndexModifier(conn);
indexer.flush();
IndexReader reader = IndexReader.open(path);
Analyzer analyzer = new StandardAnalyzer();
Searcher searcher = new IndexSearcher(reader);
QueryParser parser = new QueryParser(FIELD_DATA, analyzer);
Query query = parser.parse(text);
Hits hits = searcher.search(query);
int max = hits.length();
if (limit == 0) {
limit = max;
}
for (int i = 0; i < limit && i + offset < max; i++) {
Document doc = hits.doc(i + offset);
String q = doc.get(FIELD_QUERY);
rs.addRow(new Object[] { q });
}
// TODO keep it open if possible
reader.close();
} catch (Exception e) {
throw convertException(e);
}
return rs;
}
private static void removeAllTriggers(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TRIGGERS");
Statement stat2 = conn.createStatement();
while (rs.next()) {
String schema = rs.getString("TRIGGER_SCHEMA");
String name = rs.getString("TRIGGER_NAME");
if (name.startsWith(TRIGGER_PREFIX)) {
name = StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(name);
stat2.execute("DROP TRIGGER " + name);
}
}
}
private static void removeIndexFiles(Connection conn) throws SQLException {
String path = getIndexPath(conn);
IndexModifier index = (IndexModifier) indexers.get(path);
if (index != null) {
indexers.remove(path);
try {
index.flush();
index.close();
} catch (IOException e) {
throw convertException(e);
}
}
FileSystem.getInstance(path).deleteRecursive(path);
}
private String getQuery(Object[] row) throws SQLException { private String getQuery(Object[] row) throws SQLException {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
if (schemaName != null) { if (schemaName != null) {
...@@ -475,48 +462,85 @@ public class FullTextLucene implements Trigger { ...@@ -475,48 +462,85 @@ public class FullTextLucene implements Trigger {
SQLException e2 = new SQLException("FULLTEXT", "Error while indexing document"); SQLException e2 = new SQLException("FULLTEXT", "Error while indexing document");
e2.initCause(e); e2.initCause(e);
return e2; return e2;
}
private static void createTrigger(Connection conn, String schema, String table) throws SQLException {
Statement stat = conn.createStatement();
String trigger = StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(TRIGGER_PREFIX + table);
stat.execute("DROP TRIGGER IF EXISTS " + trigger);
StringBuffer buff = new StringBuffer("CREATE TRIGGER IF NOT EXISTS ");
buff.append(trigger);
buff.append(" AFTER INSERT, UPDATE, DELETE ON ");
buff.append(StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(table));
buff.append(" FOR EACH ROW CALL \"");
buff.append(FullTextLucene.class.getName());
buff.append("\"");
stat.execute(buff.toString());
} }
/** private static void indexExistingRows(Connection conn, String schema, String table) throws SQLException {
* Searches from the full text index for this database. FullTextLucene existing = new FullTextLucene();
* existing.init(conn, schema, null, table);
* @param conn the connection StringBuffer buff = new StringBuffer("SELECT * FROM ");
* @param text the search query buff.append(StringUtils.quoteIdentifier(schema) + "." + StringUtils.quoteIdentifier(table));
* @param limit the maximum number of rows or 0 for no limit ResultSet rs = conn.createStatement().executeQuery(buff.toString());
* @param offset the offset or 0 for no offset int columnCount = rs.getMetaData().getColumnCount();
* @return the result set while (rs.next()) {
*/ Object[] row = new Object[columnCount];
public static ResultSet search(Connection conn, String text, int limit, int offset) throws SQLException { for (int i = 0; i < columnCount; i++) {
SimpleResultSet rs = new SimpleResultSet(); row[i] = rs.getObject(i + 1);
rs.addColumn(FIELD_QUERY, Types.VARCHAR, 0, 0); }
if (text == null) { existing.fire(conn, null, row);
// this is just to query the result set columns
return rs;
} }
String path = getIndexPath(conn); }
private static IndexModifier getIndexModifier(Connection conn) throws SQLException {
try { try {
IndexModifier indexer = getIndexModifier(conn); String path = getIndexPath(conn);
indexer.flush(); IndexModifier indexer;
IndexReader reader = IndexReader.open(path); synchronized (indexers) {
Analyzer analyzer = new StandardAnalyzer(); indexer = (IndexModifier) indexers.get(path);
Searcher searcher = new IndexSearcher(reader); if (indexer == null) {
QueryParser parser = new QueryParser(FIELD_DATA, analyzer); // TODO: create flag = true means re-create
Query query = parser.parse(text); indexer = new IndexModifier(path, new StandardAnalyzer(), true);
Hits hits = searcher.search(query); indexers.put(path, indexer);
int max = hits.length(); }
if (limit == 0) {
limit = max;
}
for (int i = 0; i < limit && i + offset < max; i++) {
Document doc = hits.doc(i + offset);
String q = doc.get(FIELD_QUERY);
rs.addRow(new Object[] { q });
} }
// TODO keep it open if possible return indexer;
reader.close(); } catch (IOException e) {
} catch (Exception e) {
throw convertException(e); throw convertException(e);
} }
return rs;
} }
private static String getIndexPath(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("CALL DATABASE_PATH()");
rs.next();
String path = rs.getString(1);
if (path == null) {
throw new SQLException("FULLTEXT", "Fulltext search for in-memory databases is not supported.");
}
rs.close();
return path;
}
private void setColumns(int[] index, ArrayList keys, ArrayList columns) throws SQLException {
for (int i = 0; i < keys.size(); i++) {
String key = (String) keys.get(i);
int found = -1;
for (int j = 0; found == -1 && j < columns.size(); j++) {
String column = (String) columns.get(j);
if (column.equals(key)) {
found = j;
}
}
if (found < 0) {
throw new SQLException("FULLTEXT", "Column not found: " + key);
}
index[i] = found;
}
}
//#endif
} }
...@@ -6,16 +6,16 @@ package org.h2.jdbcx; ...@@ -6,16 +6,16 @@ package org.h2.jdbcx;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
//#ifdef JDK14
import java.io.Serializable;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
//#ifdef JDK14
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource; import javax.sql.DataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
...@@ -36,11 +36,11 @@ import org.h2.message.Message; ...@@ -36,11 +36,11 @@ import org.h2.message.Message;
* A data source for H2 database connections. It is a factory for XAConnection and Connection objects. * A data source for H2 database connections. It is a factory for XAConnection and Connection objects.
* This class is usually registered in a JNDI naming service. * This class is usually registered in a JNDI naming service.
*/ */
public class JdbcDataSource extends TraceObject implements public class JdbcDataSource extends TraceObject
//#ifdef JDK14 //#ifdef JDK14
XADataSource, DataSource, ConnectionPoolDataSource, implements XADataSource, DataSource, ConnectionPoolDataSource, Serializable, Referenceable
//#endif //#endif
Serializable, Referenceable { {
private static final long serialVersionUID = 1288136338451857771L; private static final long serialVersionUID = 1288136338451857771L;
...@@ -211,6 +211,7 @@ Serializable, Referenceable { ...@@ -211,6 +211,7 @@ Serializable, Referenceable {
* *
* @return the new reference * @return the new reference
*/ */
//#ifdef JDK14
public Reference getReference() throws NamingException { public Reference getReference() throws NamingException {
debugCodeCall("getReference"); debugCodeCall("getReference");
String factoryClassName = JdbcDataSourceFactory.class.getName(); String factoryClassName = JdbcDataSourceFactory.class.getName();
...@@ -221,9 +222,14 @@ Serializable, Referenceable { ...@@ -221,9 +222,14 @@ Serializable, Referenceable {
ref.add(new StringRefAddr("loginTimeout", String.valueOf(loginTimeout))); ref.add(new StringRefAddr("loginTimeout", String.valueOf(loginTimeout)));
return ref; return ref;
} }
//#endif
/**
*
*/
//#ifdef JDK14 //#ifdef JDK14
public XAConnection getXAConnection() throws SQLException { public XAConnection getXAConnection() throws SQLException {
int document;
debugCodeCall("getXAConnection"); debugCodeCall("getXAConnection");
int id = getNextId(XA_DATA_SOURCE); int id = getNextId(XA_DATA_SOURCE);
return new JdbcXAConnection(factory, id, url, user, password); return new JdbcXAConnection(factory, id, url, user, password);
......
...@@ -6,10 +6,12 @@ package org.h2.jdbcx; ...@@ -6,10 +6,12 @@ package org.h2.jdbcx;
import java.util.Hashtable; import java.util.Hashtable;
//#ifdef JDK14
import javax.naming.Context; import javax.naming.Context;
import javax.naming.Name; import javax.naming.Name;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.spi.ObjectFactory; import javax.naming.spi.ObjectFactory;
//#endif
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -19,7 +21,11 @@ import org.h2.message.TraceSystem; ...@@ -19,7 +21,11 @@ import org.h2.message.TraceSystem;
/** /**
* This class is used to create new JdbcDataSource objects. * This class is used to create new JdbcDataSource objects.
*/ */
public class JdbcDataSourceFactory implements ObjectFactory { public class JdbcDataSourceFactory
//#ifdef JDK14
implements ObjectFactory
//#endif
{
private static TraceSystem traceSystem; private static TraceSystem traceSystem;
private Trace trace; private Trace trace;
...@@ -46,6 +52,7 @@ public class JdbcDataSourceFactory implements ObjectFactory { ...@@ -46,6 +52,7 @@ public class JdbcDataSourceFactory implements ObjectFactory {
* @param environment unused * @param environment unused
* @return the new JdbcDataSource, or null if the reference class name is not JdbcDataSource. * @return the new JdbcDataSource, or null if the reference class name is not JdbcDataSource.
*/ */
//#ifdef JDK14
public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
trace.debug("getObjectInstance obj=" + obj + " name=" + name + " nameCtx=" + nameCtx + " environment=" + environment); trace.debug("getObjectInstance obj=" + obj + " name=" + name + " nameCtx=" + nameCtx + " environment=" + environment);
Reference ref = (Reference) obj; Reference ref = (Reference) obj;
...@@ -60,6 +67,7 @@ public class JdbcDataSourceFactory implements ObjectFactory { ...@@ -60,6 +67,7 @@ public class JdbcDataSourceFactory implements ObjectFactory {
} }
return null; return null;
} }
//#endif
TraceSystem getTraceSystem() { TraceSystem getTraceSystem() {
return traceSystem; return traceSystem;
......
...@@ -64,21 +64,25 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -64,21 +64,25 @@ implements XAConnection, XAResource, JdbcConnectionListener
connSentinel = openConnection(); connSentinel = openConnection();
getConnection(); getConnection();
} }
//#endif
/** /**
* Get the XAResource object. * Get the XAResource object.
* *
* @return itself * @return itself
*/ */
//#ifdef JDK14
public XAResource getXAResource() throws SQLException { public XAResource getXAResource() throws SQLException {
debugCodeCall("getXAResource"); debugCodeCall("getXAResource");
return this; return this;
} }
//#endif
/** /**
* Close the physical connection. * Close the physical connection.
* This method is usually called by the connection pool. * This method is usually called by the connection pool.
*/ */
//#ifdef JDK14
public void close() throws SQLException { public void close() throws SQLException {
debugCodeCall("close"); debugCodeCall("close");
try { try {
...@@ -89,31 +93,15 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -89,31 +93,15 @@ implements XAConnection, XAResource, JdbcConnectionListener
connSentinel = null; connSentinel = null;
} }
} }
//#endif
private void closeConnection(JdbcConnection conn) throws SQLException {
if (conn != null) {
conn.closeConnection();
}
}
private JdbcConnection openConnection() throws SQLException {
Properties info = new Properties();
info.setProperty("user", user);
info.setProperty("password", password);
JdbcConnection conn = new JdbcConnection(url, info);
conn.setJdbcConnectionListener(this);
if (currentTransaction != null) {
conn.setAutoCommit(false);
}
return conn;
}
/** /**
* Get a new connection. * Get a new connection.
* This method is usually called by the connection pool when there are no more connections in the pool. * This method is usually called by the connection pool when there are no more connections in the pool.
* *
* @return the connection * @return the connection
*/ */
//#ifdef JDK14
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
debugCodeCall("getConnection"); debugCodeCall("getConnection");
if (conn != null) { if (conn != null) {
...@@ -124,12 +112,14 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -124,12 +112,14 @@ implements XAConnection, XAResource, JdbcConnectionListener
conn.setJdbcConnectionListener(this); conn.setJdbcConnectionListener(this);
return conn; return conn;
} }
//#endif
/** /**
* Register a new listener for the connection. * Register a new listener for the connection.
* *
* @param listener the event listener * @param listener the event listener
*/ */
//#ifdef JDK14
public void addConnectionEventListener(ConnectionEventListener listener) { public void addConnectionEventListener(ConnectionEventListener listener) {
debugCode("addConnectionEventListener(listener)"); debugCode("addConnectionEventListener(listener)");
listeners.add(listener); listeners.add(listener);
...@@ -137,20 +127,24 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -137,20 +127,24 @@ implements XAConnection, XAResource, JdbcConnectionListener
conn.setJdbcConnectionListener(this); conn.setJdbcConnectionListener(this);
} }
} }
//#endif
/** /**
* Remove the event listener. * Remove the event listener.
* *
* @param listener the event listener * @param listener the event listener
*/ */
//#ifdef JDK14
public void removeConnectionEventListener(ConnectionEventListener listener) { public void removeConnectionEventListener(ConnectionEventListener listener) {
debugCode("removeConnectionEventListener(listener)"); debugCode("removeConnectionEventListener(listener)");
listeners.remove(listener); listeners.remove(listener);
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef JDK14
public void fatalErrorOccurred(JdbcConnection conn, SQLException e) throws SQLException { public void fatalErrorOccurred(JdbcConnection conn, SQLException e) throws SQLException {
debugCode("fatalErrorOccurred(conn, e)"); debugCode("fatalErrorOccurred(conn, e)");
for (int i = 0; i < listeners.size(); i++) { for (int i = 0; i < listeners.size(); i++) {
...@@ -160,10 +154,12 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -160,10 +154,12 @@ implements XAConnection, XAResource, JdbcConnectionListener
} }
close(); close();
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef JDK14
public void closed(JdbcConnection conn) { public void closed(JdbcConnection conn) {
debugCode("closed(conn)"); debugCode("closed(conn)");
for (int i = 0; i < listeners.size(); i++) { for (int i = 0; i < listeners.size(); i++) {
...@@ -172,16 +168,19 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -172,16 +168,19 @@ implements XAConnection, XAResource, JdbcConnectionListener
listener.connectionClosed(event); listener.connectionClosed(event);
} }
} }
//#endif
/** /**
* Get the transaction timeout. * Get the transaction timeout.
* *
* @return 0 * @return 0
*/ */
//#ifdef JDK14
public int getTransactionTimeout() throws XAException { public int getTransactionTimeout() throws XAException {
debugCodeCall("getTransactionTimeout"); debugCodeCall("getTransactionTimeout");
return 0; return 0;
} }
//#endif
/** /**
* Set the transaction timeout. * Set the transaction timeout.
...@@ -189,22 +188,26 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -189,22 +188,26 @@ implements XAConnection, XAResource, JdbcConnectionListener
* @param seconds ignored * @param seconds ignored
* @return false * @return false
*/ */
//#ifdef JDK14
public boolean setTransactionTimeout(int seconds) throws XAException { public boolean setTransactionTimeout(int seconds) throws XAException {
debugCodeCall("setTransactionTimeout", seconds); debugCodeCall("setTransactionTimeout", seconds);
return false; return false;
} }
//#endif
/** /**
* Checks if this is the same XAResource. * Checks if this is the same XAResource.
* *
* @param xares the other object * @param xares the other object
* @return true if this is the same object * @return true if this is the same object
*/ */
//#ifdef JDK14
public boolean isSameRM(XAResource xares) throws XAException { public boolean isSameRM(XAResource xares) throws XAException {
debugCode("isSameRM(xares)"); debugCode("isSameRM(xares)");
return xares == this; return xares == this;
} }
//#endif
/** /**
* Get the list of prepared transaction branches. * Get the list of prepared transaction branches.
* This method is called by the transaction manager during recovery. * This method is called by the transaction manager during recovery.
...@@ -213,6 +216,7 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -213,6 +216,7 @@ implements XAConnection, XAResource, JdbcConnectionListener
* TMNOFLAGS must be used. * TMNOFLAGS must be used.
* @return zero or more Xid objects * @return zero or more Xid objects
*/ */
//#ifdef JDK14
public Xid[] recover(int flag) throws XAException { public Xid[] recover(int flag) throws XAException {
debugCodeCall("recover", quoteFlags(flag)); debugCodeCall("recover", quoteFlags(flag));
checkOpen(); checkOpen();
...@@ -238,19 +242,14 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -238,19 +242,14 @@ implements XAConnection, XAResource, JdbcConnectionListener
JdbcUtils.closeSilently(stat); JdbcUtils.closeSilently(stat);
} }
} }
//#endif
private void checkOpen() throws XAException {
if (conn == null) {
getTrace().debug("conn==null");
throw new XAException(XAException.XAER_RMERR);
}
}
/** /**
* Prepare a transaction. * Prepare a transaction.
* *
* @param xid the transaction id * @param xid the transaction id
*/ */
//#ifdef JDK14
public int prepare(Xid xid) throws XAException { public int prepare(Xid xid) throws XAException {
debugCode("prepare("+quoteXid(xid)+")"); debugCode("prepare("+quoteXid(xid)+")");
checkOpen(); checkOpen();
...@@ -271,22 +270,26 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -271,22 +270,26 @@ implements XAConnection, XAResource, JdbcConnectionListener
getTrace().debug("return XA_OK"); getTrace().debug("return XA_OK");
return XA_OK; return XA_OK;
} }
//#endif
/** /**
* Forget a transaction. * Forget a transaction.
* This method does not have an effect for this database. * This method does not have an effect for this database.
* *
* @param xid the transaction id * @param xid the transaction id
*/ */
//#ifdef JDK14
public void forget(Xid xid) throws XAException { public void forget(Xid xid) throws XAException {
debugCode("forget("+quoteXid(xid)+")"); debugCode("forget("+quoteXid(xid)+")");
} }
//#endif
/** /**
* Roll back a transaction. * Roll back a transaction.
* *
* @param xid the transaction id * @param xid the transaction id
*/ */
//#ifdef JDK14
public void rollback(Xid xid) throws XAException { public void rollback(Xid xid) throws XAException {
debugCode("rollback("+quoteXid(xid)+")"); debugCode("rollback("+quoteXid(xid)+")");
try { try {
...@@ -297,13 +300,15 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -297,13 +300,15 @@ implements XAConnection, XAResource, JdbcConnectionListener
getTrace().debug("rolled back"); getTrace().debug("rolled back");
currentTransaction = null; currentTransaction = null;
} }
//#endif
/** /**
* End a transaction. * End a transaction.
* *
* @param xid the transaction id * @param xid the transaction id
* @param flags TMSUCCESS, TMFAIL, or TMSUSPEND * @param flags TMSUCCESS, TMFAIL, or TMSUSPEND
*/ */
//#ifdef JDK14
public void end(Xid xid, int flags) throws XAException { public void end(Xid xid, int flags) throws XAException {
debugCode("end("+quoteXid(xid)+", "+quoteFlags(flags)+")"); debugCode("end("+quoteXid(xid)+", "+quoteFlags(flags)+")");
// TODO transaction end: implement this method // TODO transaction end: implement this method
...@@ -315,65 +320,15 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -315,65 +320,15 @@ implements XAConnection, XAResource, JdbcConnectionListener
throw new XAException(XAException.XAER_OUTSIDE); throw new XAException(XAException.XAER_OUTSIDE);
} }
} }
//#endif
private String quoteFlags(int flags) {
StringBuffer buff = new StringBuffer();
if ((flags & XAResource.TMENDRSCAN) != 0) {
buff.append("|XAResource.TMENDRSCAN");
}
if ((flags & XAResource.TMFAIL) != 0) {
buff.append("|XAResource.TMFAIL");
}
if ((flags & XAResource.TMJOIN) != 0) {
buff.append("|XAResource.TMJOIN");
}
if ((flags & XAResource.TMONEPHASE) != 0) {
buff.append("|XAResource.TMONEPHASE");
}
if ((flags & XAResource.TMRESUME) != 0) {
buff.append("|XAResource.TMRESUME");
}
if ((flags & XAResource.TMSTARTRSCAN) != 0) {
buff.append("|XAResource.TMSTARTRSCAN");
}
if ((flags & XAResource.TMSUCCESS) != 0) {
buff.append("|XAResource.TMSUCCESS");
}
if ((flags & XAResource.TMSUSPEND) != 0) {
buff.append("|XAResource.TMSUSPEND");
}
if ((flags & XAResource.XA_OK) != 0) {
buff.append("|XAResource.XA_OK");
}
if ((flags & XAResource.XA_RDONLY) != 0) {
buff.append("|XAResource.XA_RDONLY");
}
if (buff.length() == 0) {
buff.append("|XAResource.TMNOFLAGS");
}
return buff.toString().substring(1);
}
private String quoteXid(Xid xid) {
StringBuffer buff = new StringBuffer();
buff.append("\"f:");
buff.append(xid.getFormatId());
buff.append(",bq:");
buff.append(ByteUtils.convertBytesToString(xid.getBranchQualifier()));
buff.append(",gx:");
buff.append(ByteUtils.convertBytesToString(xid.getGlobalTransactionId()));
buff.append(",c:");
buff.append(xid.getClass().getName());
buff.append("\"");
return buff.toString();
}
/** /**
* Start or continue to work on a transaction. * Start or continue to work on a transaction.
* *
* @param xid the transaction id * @param xid the transaction id
* @param flags TMNOFLAGS, TMJOIN, or TMRESUME * @param flags TMNOFLAGS, TMJOIN, or TMRESUME
*/ */
//#ifdef JDK14
public void start(Xid xid, int flags) throws XAException { public void start(Xid xid, int flags) throws XAException {
debugCode("start("+quoteXid(xid)+", "+quoteFlags(flags)+")"); debugCode("start("+quoteXid(xid)+", "+quoteFlags(flags)+")");
if (flags == TMRESUME) { if (flags == TMRESUME) {
...@@ -391,18 +346,15 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -391,18 +346,15 @@ implements XAConnection, XAResource, JdbcConnectionListener
getTrace().debug("currentTransaction=xid"); getTrace().debug("currentTransaction=xid");
currentTransaction = xid; currentTransaction = xid;
} }
//#endif
private XAException convertException(SQLException e) {
getTrace().debug("throw XAException("+e.getMessage()+")");
return new XAException(e.getMessage());
}
/** /**
* Commit a transaction. * Commit a transaction.
* *
* @param xid the transaction id * @param xid the transaction id
* @param onePhase use a one-phase protocol if true * @param onePhase use a one-phase protocol if true
*/ */
//#ifdef JDK14
public void commit(Xid xid, boolean onePhase) throws XAException { public void commit(Xid xid, boolean onePhase) throws XAException {
debugCode("commit("+quoteXid(xid)+", "+onePhase+")"); debugCode("commit("+quoteXid(xid)+", "+onePhase+")");
Statement stat = null; Statement stat = null;
...@@ -442,8 +394,92 @@ implements XAConnection, XAResource, JdbcConnectionListener ...@@ -442,8 +394,92 @@ implements XAConnection, XAResource, JdbcConnectionListener
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef JDK14
public String toString() { public String toString() {
return getTraceObjectName() + ": url=" + url + " user=" + user; return getTraceObjectName() + ": url=" + url + " user=" + user;
} }
private void closeConnection(JdbcConnection conn) throws SQLException {
if (conn != null) {
conn.closeConnection();
}
}
private JdbcConnection openConnection() throws SQLException {
Properties info = new Properties();
info.setProperty("user", user);
info.setProperty("password", password);
JdbcConnection conn = new JdbcConnection(url, info);
conn.setJdbcConnectionListener(this);
if (currentTransaction != null) {
conn.setAutoCommit(false);
}
return conn;
}
private XAException convertException(SQLException e) {
getTrace().debug("throw XAException("+e.getMessage()+")");
return new XAException(e.getMessage());
}
private String quoteXid(Xid xid) {
StringBuffer buff = new StringBuffer();
buff.append("\"f:");
buff.append(xid.getFormatId());
buff.append(",bq:");
buff.append(ByteUtils.convertBytesToString(xid.getBranchQualifier()));
buff.append(",gx:");
buff.append(ByteUtils.convertBytesToString(xid.getGlobalTransactionId()));
buff.append(",c:");
buff.append(xid.getClass().getName());
buff.append("\"");
return buff.toString();
}
private String quoteFlags(int flags) {
StringBuffer buff = new StringBuffer();
if ((flags & XAResource.TMENDRSCAN) != 0) {
buff.append("|XAResource.TMENDRSCAN");
}
if ((flags & XAResource.TMFAIL) != 0) {
buff.append("|XAResource.TMFAIL");
}
if ((flags & XAResource.TMJOIN) != 0) {
buff.append("|XAResource.TMJOIN");
}
if ((flags & XAResource.TMONEPHASE) != 0) {
buff.append("|XAResource.TMONEPHASE");
}
if ((flags & XAResource.TMRESUME) != 0) {
buff.append("|XAResource.TMRESUME");
}
if ((flags & XAResource.TMSTARTRSCAN) != 0) {
buff.append("|XAResource.TMSTARTRSCAN");
}
if ((flags & XAResource.TMSUCCESS) != 0) {
buff.append("|XAResource.TMSUCCESS");
}
if ((flags & XAResource.TMSUSPEND) != 0) {
buff.append("|XAResource.TMSUSPEND");
}
if ((flags & XAResource.XA_OK) != 0) {
buff.append("|XAResource.XA_OK");
}
if ((flags & XAResource.XA_RDONLY) != 0) {
buff.append("|XAResource.XA_RDONLY");
}
if (buff.length() == 0) {
buff.append("|XAResource.TMNOFLAGS");
}
return buff.toString().substring(1);
}
private void checkOpen() throws XAException {
if (conn == null) {
getTrace().debug("conn==null");
throw new XAException(XAException.XAER_RMERR);
}
}
//#endif
} }
...@@ -47,13 +47,6 @@ implements Xid ...@@ -47,13 +47,6 @@ implements Xid
} }
} }
// private JdbcXid(JdbcDataSourceFactory factory, int id, Xid xid) {
// setTrace(factory.getTrace(), TraceObject.XID, id);
// this.formatId = xid.getFormatId();
// this.branchQualifier = clone(xid.getBranchQualifier());
// this.globalTransactionId = clone(xid.getGlobalTransactionId());
// }
/** /**
* INTERNAL * INTERNAL
*/ */
...@@ -68,12 +61,6 @@ implements Xid ...@@ -68,12 +61,6 @@ implements Xid
return buff.toString(); return buff.toString();
} }
// private byte[] clone(byte[] data) {
// byte[] d2 = new byte[data.length];
// System.arraycopy(data, 0, d2, 0, data.length);
// return d2;
// }
/** /**
* Get the format id. * Get the format id.
* *
......
...@@ -600,7 +600,7 @@ public class PgServerThread implements Runnable { ...@@ -600,7 +600,7 @@ public class PgServerThread implements Runnable {
} }
} }
} }
r = new InputStreamReader(getClass().getResourceAsStream("pg_catalog.sql")); r = new InputStreamReader(PgServerThread.class.getResourceAsStream("pg_catalog.sql"));
ScriptReader reader = new ScriptReader(new BufferedReader(r)); ScriptReader reader = new ScriptReader(new BufferedReader(r));
while (true) { while (true) {
String sql = reader.readStatement(); String sql = reader.readStatement();
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package org.h2.tools; package org.h2.tools;
//#ifdef AWT
import java.awt.Button; import java.awt.Button;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
...@@ -24,11 +25,12 @@ import java.awt.event.MouseEvent; ...@@ -24,11 +25,12 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import org.h2.util.IOUtils;
import java.io.InputStream; import java.io.InputStream;
//#endif
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.server.ShutdownHandler; import org.h2.server.ShutdownHandler;
import org.h2.util.IOUtils;
import org.h2.util.StartBrowser; import org.h2.util.StartBrowser;
/** /**
...@@ -37,11 +39,17 @@ import org.h2.util.StartBrowser; ...@@ -37,11 +39,17 @@ import org.h2.util.StartBrowser;
* Otherwise, a small window opens. * Otherwise, a small window opens.
* *
*/ */
public class Console implements ActionListener, MouseListener, ShutdownHandler { public class Console implements
//#ifdef AWT
ActionListener, MouseListener,
//#endif
ShutdownHandler {
//#ifdef AWT
private Font font; private Font font;
private Image icon; private Image icon;
private Frame frame; private Frame frame;
//#endif
private static final int EXIT_ERROR = 1; private static final int EXIT_ERROR = 1;
private Server web, tcp, pg; private Server web, tcp, pg;
...@@ -92,10 +100,11 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler { ...@@ -92,10 +100,11 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler {
System.out.println(pg.getStatus()); System.out.println(pg.getStatus());
} }
} }
//#ifdef AWT
if (!GraphicsEnvironment.isHeadless()) { if (!GraphicsEnvironment.isHeadless()) {
font = new Font("Dialog", Font.PLAIN, 11); font = new Font("Dialog", Font.PLAIN, 11);
try { try {
InputStream in = getClass().getResourceAsStream("/org/h2/res/h2.png"); InputStream in = Console.class.getResourceAsStream("/org/h2/res/h2.png");
if (in != null) { if (in != null) {
byte[] imageData = IOUtils.readBytesAndClose(in, -1); byte[] imageData = IOUtils.readBytesAndClose(in, -1);
icon = Toolkit.getDefaultToolkit().createImage(imageData); icon = Toolkit.getDefaultToolkit().createImage(imageData);
...@@ -107,6 +116,8 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler { ...@@ -107,6 +116,8 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler {
e.printStackTrace(); e.printStackTrace();
} }
} }
//#endif
// start browser anyway (even if the server is already running) // start browser anyway (even if the server is already running)
// because some people don't look at the output, // because some people don't look at the output,
// but are wondering why nothing happens // but are wondering why nothing happens
...@@ -137,13 +148,16 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler { ...@@ -137,13 +148,16 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler {
pg.stop(); pg.stop();
pg = null; pg = null;
} }
//#ifdef AWT
if (frame != null) { if (frame != null) {
frame.dispose(); frame.dispose();
frame = null; frame = null;
} }
//#endif
System.exit(0); System.exit(0);
} }
//#ifdef AWT
private boolean createTrayIcon() { private boolean createTrayIcon() {
try { try {
// SystemTray.isSupported(); // SystemTray.isSupported();
...@@ -260,10 +274,18 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler { ...@@ -260,10 +274,18 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler {
frame.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); frame.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2);
frame.setVisible(true); frame.setVisible(true);
} }
private void startBrowser() {
if (web != null) {
StartBrowser.openURL(web.getURL());
}
}
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand(); String command = e.getActionCommand();
if ("exit".equals(command)) { if ("exit".equals(command)) {
...@@ -274,44 +296,49 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler { ...@@ -274,44 +296,49 @@ public class Console implements ActionListener, MouseListener, ShutdownHandler {
showWindow(false); showWindow(false);
} }
} }
//#endif
private void startBrowser() {
if (web != null) {
StartBrowser.openURL(web.getURL());
}
}
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) { if (e.getButton() == MouseEvent.BUTTON1) {
startBrowser(); startBrowser();
} }
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void mouseEntered(MouseEvent e) { public void mouseEntered(MouseEvent e) {
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void mouseExited(MouseEvent e) { public void mouseExited(MouseEvent e) {
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
} }
//#endif
/** /**
* INTERNAL * INTERNAL
*/ */
//#ifdef AWT
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
} }
//#endif
} }
...@@ -86,6 +86,7 @@ public class JdbcUtils { ...@@ -86,6 +86,7 @@ public class JdbcUtils {
Class d = ClassUtils.loadClass(driver); Class d = ClassUtils.loadClass(driver);
if (java.sql.Driver.class.isAssignableFrom(d)) { if (java.sql.Driver.class.isAssignableFrom(d)) {
return DriverManager.getConnection(url, prop); return DriverManager.getConnection(url, prop);
//#ifdef JDK14
} else if (javax.naming.Context.class.isAssignableFrom(d)) { } else if (javax.naming.Context.class.isAssignableFrom(d)) {
// JNDI context // JNDI context
try { try {
...@@ -101,6 +102,7 @@ public class JdbcUtils { ...@@ -101,6 +102,7 @@ public class JdbcUtils {
} catch (NamingException e) { } catch (NamingException e) {
throw Message.convert(e); throw Message.convert(e);
} }
//#endif
} else { } else {
// Don't know, but maybe it loaded a JDBC Driver // Don't know, but maybe it loaded a JDBC Driver
return DriverManager.getConnection(url, prop); return DriverManager.getConnection(url, prop);
......
...@@ -38,18 +38,6 @@ public class ValueArray extends Value { ...@@ -38,18 +38,6 @@ public class ValueArray extends Value {
return values; return values;
} }
public int compareTo(ValueArray other, CompareMode mode) throws SQLException {
for (int i = 0; i < values.length; i++) {
Value v1 = values[i];
Value v2 = other.values[i];
int comp = v1.compareTo(v2, mode);
if (comp != 0) {
return comp;
}
}
return 0;
}
public int getType() { public int getType() {
return Value.ARRAY; return Value.ARRAY;
} }
...@@ -71,43 +59,23 @@ public class ValueArray extends Value { ...@@ -71,43 +59,23 @@ public class ValueArray extends Value {
return buff.toString(); return buff.toString();
} }
// public String getJavaString() {
// StringBuffer buff = new StringBuffer();
// buff.append('{');
// for (int i = 0; i < values.length; i++) {
// if (i > 0) {
// buff.append(", ");
// }
// buff.append(values[i].getJavaString());
// }
// buff.append('}');
// return buff.toString();
// }
protected int compareSecure(Value o, CompareMode mode) throws SQLException { protected int compareSecure(Value o, CompareMode mode) throws SQLException {
ValueArray v = (ValueArray) o; ValueArray v = (ValueArray) o;
if (values == v.values) { if (values == v.values) {
return 0; return 0;
} }
if (values.length != v.values.length) { int l = values.length;
return values.length > v.values.length ? 1 : -1; int ol = v.values.length;
} int len = Math.min(l, ol);
for (int i = 0; i < values.length; i++) { for (int i = 0; i < len; i++) {
Value v1 = values[i]; Value v1 = values[i];
Value v2 = v.values[i]; Value v2 = v.values[i];
int c; int comp = v1.compareTo(v2, mode);
if (v1 == ValueNull.INSTANCE) { if (comp != 0) {
c = v2 == ValueNull.INSTANCE ? 0 : -1; return comp;
} else if (v2 == ValueNull.INSTANCE) {
c = 1;
} else {
c = v1.compareSecure(v2, mode);
}
if (c != 0) {
return c;
} }
} }
return 0; return l > ol ? 1 : l == ol ? 0 : -1;
} }
public Object getObject() throws SQLException { public Object getObject() throws SQLException {
......
...@@ -150,49 +150,11 @@ java org.h2.test.TestAll timer ...@@ -150,49 +150,11 @@ java org.h2.test.TestAll timer
/* /*
FAQ, build? translation
History
Now using custom toString() for most JDBC objects and commands.
Nested temporary views (SELECT * FROM (SELECT ...)) with parameters didn't work in some cases. Fixed.
CSV: Using an empty field delimiter didn't work (a workaround was using char(0)). Fixed.
Performance: use BufferedReader, BufferedWriter everywhere where possible (BufferInputStream alone doesn't help)
document Memory-Only databases > In-Memory Databases
By default, when the last connection to a in-memory database is closed, the contents are lost.
This can be disabled by adding this to the database URL: ;DB_CLOSE_DELAY=-1
That means to keep the contents of an in-memory database as long as the virtual machine is alive, use
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
History:
The default value for h2.emergencySpaceInitial is now 256 KB (to speed up creating encrypted databases)
Eduardo Velasques has translated the H2 Console and the error messages to Brazilian Portuguese. Thanks a lot!
Creating a table from GROUP_CONCAT didn't work if the data was longer than 255 characters
document translation (what files to translate)
Known Problems: Known Problems:
link to history page, bug page link to history page, bug page
Add a link to the google code bug page Add a link to the google code bug page
Email: h2@olivercomputing.com Google Android support: use 'ant codeswitchAndroid' to switch the source code to Android.
Message:
Very cool project, I sent you a few euros yesterday.
I have a feature suggestion in the way that you sort array columns in ORDER BY. To take a concrete example, given
(0,1)
(0,1,1)
(0,2)
then PostgreSQL would order them as above, but H2 orders them as:
(0,1)
(0,2)
(0,1,1)
i.e. the ordering is evidently applied so that the array length is used in the count. While either way could be arguable, I would argue for the PostgreSQL ordering for two reasons:
- PostgreSQL compatibility itself
- Because, at least for my use case, I am using the arrays to represent XML hierarchy information. The first (PG) way of ordering naturally represents the XML document node order, but the current H2 way does not. Given the variable hierarchy of an XML document, such ordering can be difficult to do efficiently in a relational "shredded" node representation.
So, given that arrays are noted as experimental at this point, I thought I would ask if you could change their ordering scheme to match PostgreSQL's. Alternatively, perhaps a system variable could be used to pre-select the desired ordering. Thanks.
Phil Oliver
implement & test: checkpoint commits running transactions implement & test: checkpoint commits running transactions
......
...@@ -84,6 +84,7 @@ public class TestCluster extends TestBase { ...@@ -84,6 +84,7 @@ public class TestCluster extends TestBase {
n1.stop(); n1.stop();
// re-create the cluster // re-create the cluster
DeleteDbFiles.main(new String[] { "-dir", baseDir + "/node2", "-quiet" });
CreateCluster.main(new String[] { "-urlSource", "jdbc:h2:file:" + baseDir + "/node1/test", "-urlTarget", CreateCluster.main(new String[] { "-urlSource", "jdbc:h2:file:" + baseDir + "/node1/test", "-urlTarget",
"jdbc:h2:file:" + baseDir + "/node2/test", "-user", "sa", "-serverlist", "jdbc:h2:file:" + baseDir + "/node2/test", "-user", "sa", "-serverlist",
"localhost:9091,localhost:9092" }); "localhost:9091,localhost:9092" });
...@@ -92,6 +93,8 @@ public class TestCluster extends TestBase { ...@@ -92,6 +93,8 @@ public class TestCluster extends TestBase {
n2 = org.h2.tools.Server.createTcpServer( n2 = org.h2.tools.Server.createTcpServer(
new String[] { "-tcpPort", "9092", "-baseDir", baseDir + "/node2" }).start(); new String[] { "-tcpPort", "9092", "-baseDir", baseDir + "/node2" }).start();
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9091,localhost:9092/test", "sa", "");
stat = conn.createStatement();
stat.execute("CREATE TABLE BOTH(ID INT)"); stat.execute("CREATE TABLE BOTH(ID INT)");
n1.stop(); n1.stop();
......
--- special grammar and test cases --------------------------------------------------------------------------------------------- --- special grammar and test cases ---------------------------------------------------------------------------------------------
create table test(id int primary key, data array);
> ok
insert into test values(1, (1, 1)), (2, (1, 2)), (3, (1, 1, 1));
> update count: 3
select * from test order by data;
> ID DATA
> -- ---------
> 1 (1, 1)
> 3 (1, 1, 1)
> 2 (1, 2)
> rows (ordered): 3
drop table test;
> ok
CREATE TABLE FOO (A CHAR(10)); CREATE TABLE FOO (A CHAR(10));
> ok > ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论