提交 1ff784e3 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 eb6e04c3
...@@ -37,776 +37,22 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -37,776 +37,22 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<br /><a name="changelog"></a> <br /><a name="changelog"></a>
<h2>Change Log</h2> <h2>Change Log</h2>
<h3>Version 1.0 (Current)</h3> The up-to-date change log is available here:
<a href="http://groups.google.com/group/h2-database/web/change-log">
<h3>Version 1.0.60 (2007-10-20)</h3><ul> http://groups.google.com/group/h2-database/web/change-log
<li>JdbcXAConnection: starting a transaction before getting the connection didn't switch off autocommit. </a>
</li><li>User defined aggregate functions are not supported.
</li><li>Server.shutdownTcpServer was blocked when first called with force=false and then force=true.
Now documentation is improved, and it is no longer blocked.
</li><li>Stack traces did not include the SQL statement in all cases where they could have.
Also, stack traces with SQL statement are now shorter.
</li><li>Linked tables: now tables in non-default schemas are supported as well
</li><li>New Italian translation from PierPaolo Ucchino. Thanks a lot!
</li><li>CSV: New methods to set the escape character and field delimiter in the Csv tool and the CSVWRITE and CSVREAD methods.
</li><li>Prepared statements could not be used after data definition statements (creating tables and so on). Fixed.
</li><li>PreparedStatement.setMaxRows could not be changed to a higher value after the statement was executed.
</li><li>The H2 Console could not connect twice to the same H2 embedded database at the same time. Fixed.
</li><li>CSVREAD, RUNSCRIPT and so on now support URLs as well, using
URL.openStream(). Example: select * from csvread('jar:file:///c:/temp/test.jar!/test.csv');
</li></ul>
<h3>Version 1.0.59 (2007-10-03)</h3><ul>
<li>When the data type was unknown in a subquery, sometimes the wrong exception (ArrayIndexOutOfBounds) was thrown. Fixed.
</li><li>If the process was killed while the database was running, sometimes the database could not be opened
('double allocation') except when the system property h2.check was set to false. Fixed.
</li><li>Multi-threaded kernel (MULTI_THREADED=1): A synchronization problem has been fixed.
</li><li>A PreparedStatement that was cancelled could not be reused. Fixed.
</li><li>H2 Console: Progress information when logging into a H2 embedded database (useful when opening a database is slow).
</li><li>When the database was closed while logging was disabled (LOG 0), re-opening the database was slow. Fixed.
</li><li>Fulltext search is now documented (in the Tutorial).
</li><li>The Console did not refresh the table list if the CREATE TABLE statement started with a comment. Fixed.
</li><li>When creating a table using CREATE TABLE .. AS SELECT, the precision for some data types (for example VARCHAR)
was set to the default precision. Fixed.
</li><li>When using the (undocumented) in-memory file system (jdbc:h2:memFS:x or jdbc:h2:memLZF:x), and using
multiple connections, a ConcurrentModificationException could occur. Fixed.
</li><li>REGEXP compatibility: So far String.matches was used, but for compatibility with MySQL, now Matcher.find is used.
</li><li>SCRIPT: the SQL statements in the result set now include the terminating semicolon as well. Simplifies copy and paste.
</li><li>When using a subquery with group by as a table, some columns could not be used in the where condition
in the outer query. Example: SELECT * FROM (SELECT ID, COUNT(*) C FROM TEST) WHERE C > 100. Fixed.
</li><li>Views with subqueries as tables and queries with nested subqueries as tables did not always work. Fixed.
</li><li>Compatibility: comparing columns with constants that are out of range does not throw an exception.
</li></ul>
<h3>Version 1.0.58 (2007-09-15)</h3><ul>
<li>System.exit is no longer called by the WebServer, the Console and the Server tool
(except to set the exit code if required). This is important when using OSGi.
</li><li>Optimization for independent subqueries. For example, this query can now an index:
SELECT * FROM TEST WHERE ID = (SELECT MAX(ID) FROM TEST)
This can be disabled by setting the system property h2.optimizeSubqueryCache to false.
</li><li>The explain plan now says: /* direct lookup query */ if the query can be processed directly without reading rows,
for example when using MIN(indexed column), MAX(indexed column), or COUNT(*).
</li><li>When using IFNULL, NULLIF, COALESCE, LEAST, or GREATEST,
and the first parameter was ?, an exception was thrown.
Now the highest data type of all parameters is used.
</li><li>When comparing TINYINT or SMALLINT columns against constants, the index was not used. Fixed.
</li><li>Maven 2: new version are now automatically synced with the central repositories.
</li><li>The default value for MAX_MEMORY_UNDO is now 100000.
</li><li>The documentation indexer does no longer index Japanese pages.
If somebody knows how to split Japanese into words please post it.
</li><li>Oracle compatibility: SYSDATE now returns a timestamp. CHR(..) is now an alias for CHAR(..).
</li><li>After deleting data, empty space in the database files was not efficiently reused
(but it was reused when opening the database). This has been fixed.
</li><li>About 230 bytes per database was leaked. This is a problem for applications
opening and closing many thousand databases. The main problem: a shutdown hook
was added but never removed. Fixed. In JDK 1.4, there is an additionally problem,
see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4197876.
A workaround has been implemented.
</li><li>Optimization for COLUMN IN(.., NULL) if the column does not allow NULL values.
</li><li>Using spaces in column and table aliases was not supported when used inside a view or temporary view.
</li><li>The version (build) number is now included in the manifest file.
</li><li>In some systems, SecureRandom.generateSeed is very slow (taking one minute or more).
For those cases, an alternative method is used that takes less than one second.
</li><li>The database file sizes are now increased at most 32 MB at any time.
</li><li>New method DatabaseEventListener.opened that is called just after opening a database.
</li><li>When using the Console with Internet Explorer 6.0 or 7.0, a Javascript error was thrown after clearing the query.
</li><li>A database can now be opened even if class of a user defined function is not in the classpath.
Trying to call the function will throws an exception.
</li><li>User defined functions and constants may not overload built-in functions and constants.
This didn't work before, but now trying to create such an object will fail.
</li><li>Improved MultiDimension tool (for spatial queries): in the last few releases the tool was actually
slower than using a regular query (because index lookup got faster, and because the tool didn't
support prepared statements) Now the tool generates prepared statements,
and the performance is better again (about 5 times faster for a reasonable amount of data).
</li><li>Adding a foreign key or when re-enabling referential integrity for a table failed when checking
was enabled and the reference contained NULL.
</li><li>For PgServer, character encoding other than UTF-8 did not work correctly. Fixed.
</li><li>Using a function in a GROUP BY expression that is used in a view as a condition did not always work.
</li></ul>
<h3>Version 1.0.57 (2007-08-25)</h3><ul>
<li>New experimental feature MVCC (multi version concurrency control).
Can be set as a option when opening the database (jdbc:h2:test;MVCC=TRUE)
or as a system property (-Dh2.mvcc=true). This is work-in-progress, use it at your own risk. Feedback is welcome.
</li><li>The version number is now major.minor.micro where micro is the build number.
Not all version are public, so there may be gaps in the micro. The minor changes when there is a file format change.
</li><li>The backup tool (org.h2.tools.Backup) did not work. The restore tool did not work when the -db parameter was used. Fixed.
The documentation of the backup tool has been changed: only one database may be backed up at any time.
</li><li>Opening large read-only databases was very slow. Fixed.
</li><li>New Japanese translation of the error messages thanks to Ikemoto Masahiro. Thanks a lot!
</li><li>Disabling / enabling referential integrity for a table can now be used inside a transaction.
</li><li>Rights checking for dynamic tables (SELECT * FROM (SELECT ...)) did not work. Fixed.
</li><li>Creating more than 10 views that depend on each other was very slow. Reconnecting was slow as well. Fixed.
</li><li>When used as as Servlet, the H2 Console did not work with SSL (using Tomcat). Fixed.
</li><li>When altering a table with foreign key constraint, if there was no manual index created
for the referenced columns, the automatically created index was dropped while still being used. Fixed.
</li><li>Check and foreign key constraints now checks if the existing data is consistent (this can be disabled by appending NOCHECK).
It is also possible to check existing data when re-enabling referential integrity for a table.
</li><li>Some unit tests failed on Linux because the file system works differently. The unit tests are fixed and should work now.
</li><li>Can now incrementally translate the documentation. See also FAQ.
</li><li>Improved error messages: some tools can't show the root cause of an exception.
Adding the message of the root cause to the message of the thrown exception now where it makes sense.
</li><li>The H2 Console can now connect to databases using JNDI. The driver class name must be a javax.naming.Context,
(for example javax.naming.InitialContext), and the URL the resource name (for example java:comp/env/jdbc/Test).
This should also work for linked tables.
</li><li>Google translate did not work for the H2 homepage. It should be fixed now.
</li><li>The CONVERT function did not work with views when using UNION.
</li><li>The build now issues a warning if the source code is switched to the wrong version.
</li><li>The default lock mode is now read committed instead of serialized.
</li><li>PG server: data was truncated when reading large VARCHAR columns and decimal columns.
</li><li>PG server: when the same database was accessed multiple times using the PostgreSQL ODBC driver,
the pg_catalog schema update failed, and connecting to the database was not possible. Fixed.
</li><li>Some file operations didn't work for files in the root directory. Fixed.
</li><li>In the Restore tool, the parameter -file did not work. Fixed.
</li><li>Two-phase commit: commit with transaction name was only supported in the recovery scan.
Now it is always supported.
</li><li>The column name C_CURRENT_TIMESTAMP did not work in the last release.
</li><li>OpenOffice compatibility: support database name in column names.
</li></ul>
<h3>Version 1.0.56 (2007-08-02)</h3><ul>
<li>A new tool to help translation has been implemented: src/tools/org/h2/tools/i18n/PrepareTranslation.
This tool can detect delta changes in the original (English) and prepends '#' in translation if the original
text was changed. It can also extract text from the user documentation (however, it is incomplete).
</li><li>The error messages (src/main/org/h2/res/_*.*) can now be translated.
</li><li>Part of the documentation has been translated to Japanese by Yusuke Fukushima.
</li><li>Some Unicode characters where not supported as identifier name.
Thanks Yusuke Fukushima for reporting this problem.
</li><li>The default value DEFAULT_MAX_LENGTH_INPLACE_LOB has been changed from 128 to 1024.
</li><li>A server that implements the PostgreSQL protocol is now included and documented.
That means, the PostgreSQL ODBC driver can be used to access a H2 database.
See in the documentation for details.
</li><li>The experimental H2 ODBC driver has been removed.
</li><li>The default value for h2.defaultMaxMemoryUndo is now 50000.
This avoids out of memory problems when using large transactions,
however large transactions are slower because they are buffered to disk.
To disable, use -Dh2.defaultMaxMemoryUndo=2000000000.
</li><li>Support for regular expression function REGEXP_REPLACE(expression, regex, replacement)
and regular expression LIKE: expression REGEXP matchExpression. However, indexes are not yet used.
</li><li>The old view implementation has been removed.
</li><li>The SysTray tool has been removed, because JDK 1.6 has native support for system tray icons.
Use the Console tool (org.h2.tools.Console) automatically installs a system tray icon if JDK 1.6 is used.
</li><li>H2 Console: In the last release, the shutdown button did not work. Fixed.
</li><li>Referential integrity can now be disabled using
SET REFERENTIAL_INTEGRITY FALSE. It can also be disable only
for one table using ALTER TABLE SET REFERENTIAL_INTEGRITY FALSE.
</li><li>The Backup and Restore tools, and the BACKUP command did not back up LOBs when
h2.lobFilesInDirectories was enabled. Fixed.
</li><li>Calculation of cache memory usage has been improved.
</li><li>In some situations record were released too late from the cache. Fixed.
</li><li>The cache size is now measured in KB instead of blocks of 128 byte.
</li><li>CREATE TABLE ... AS SELECT now needs less memory. While inserting the rows, the undo
log is temporarily disabled. This avoid out of memory problems when creating large tables.
</li><li>The per session undo log can now be disabled. This setting is useful for bulk operations
that don't need to be atomic, like bulk delete or update.
</li><li>The database file could get corrupted when there was an OutOfMemoryException in the middle of inserting a row.
</li><li>Optimization for WHERE NOT(...) and WHERE [NOT] booleanFlagColumn.
This can be disabled using the system property h2.optimizeNot.
</li><li>Optimization for conditions like WHERE A=B AND B=X (A=X is added). This often appears in joins.
This can be disabled using the system property h2.optimizeTwoEquals.
</li><li>Documentation: the source code in 'Compacting a Database' was incorrect. Fixed.
</li><li>In the H2 Console, result sets could not be modified because the default result set type is now forward only.
For H2, now uses scrollable result sets. Also for other databases, but only when the query starts with @EDIT.
</li><li>Views using UNION did not work correctly. Fixed.
</li><li>Function tables did not work with views and EXPLAIN. Fixed.
</li></ul>
<h3>Version 1.0.55 (2007-07-12)</h3><ul>
<li>Support for the system property baseDir. This works for embedded databases as well. The setting is supported
by the H2 Console using -Dh2.baseDir or -baseDir
</li><li>LIKE ESCAPE did not work correctly if the pattern was % or _, followed by an escape character, followed by %. Fixed.
</li><li>PostgreSQL compatibility: SET SEARCH_PATH, SERIAL, CURRENT_USER, E'text', $1.
</li><li>In some situations, when many tables with LOB columns were modified (ALTER TABLE), large objects were deleted. Fixed.
</li><li>CREATE TABLE AS SELECT .. UNION .. did not work. Fixed.
</li><li>New column ID for INFORMATION_SCHEMA.INDEXES, SEQUENCES, USERS, ROLES, RIGHTS,
FUNCTION_ALIASES, SCHEMATA, VIEWS, CONSTRAINTS, CONSTANTS, DOMAINS, TRIGGERS.
</li><li>If large result sets (backed by a temporary file) where not closed, the file was not deleted.
Now, the default result set type is FETCH_FORWARD. This means temp files are deleted
automatically (without having to close the result set explicitly). But it also means
ResultSet.beforeFirst can only be called for scrollable result sets. To create a scrollable result set,
use Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY).
</li><li>PreparedStatement.getMetaData is now implemented.
</li><li>Now PreparedStatement.setBigDecimal(..) can be called with an object of a derived class
if the system property h2.allowBigDecimalExtensions is set to true.
</li><li>The default database name in the documentation is now jdbc:h2:~/test. Like this, the database
is stored in the user home directory (system property user.home). Of course storing the database
in the current working directory (as in jdbc:h2:test) still works. Using the user directory avoids
the problem that the database is not found if the application runs in another directory than
the console.
</li><li>The SQL statement SET ASSERT has been deprecated, because Constants.CHECK is now final.
To disable assertions (and improve performance), the system property h2.check can be used.
Executing SET ASSERT still works, but has no effect.
</li><li>In the READ_COMMITTED mode, when the multi-threaded kernel is enabled,
read locks are now acquired but released immediately after a query.
</li><li>The default trace level for JdbcDataSourceFactory was DEBUG, so when using data sources a trace file
was always created. Now the default trace level is ERROR, and the file is only created if necessary.
</li><li>PooledConnection.getConnection took a long time if only one connection was open at any time. Fixed.
</li><li>Referential integrity violation: Two different SQL states are now used for missing parent / existing child.
</li><li>DatabaseEventListener.exceptionThrown has a new parameter: SQL
</li><li>For compatibility reasons, the catalog name can now be used in queries: SELECT * FROM TESTDB.PUBLIC.TEST
</li><li>If SHUTDOWN IMMEDIATELY was called, then the connection was not closed and the database
opened from somebody else at the same time, in some cases this could result in errors with LOB files. Fixed.
</li><li>The new view implementation is now enabled by default.
To use the old implementation, set the system property 'h2.indexOld' to true
(java -Dh2.indexOld=true ..., or in source code Constants.INDEX_OLD = true).
If no problems are found, the old implementation will be removed in the next release.
The old implementation does not work with multi-level nested temporary views
(select * from (select * from (select * from test))).
</li><li>The new view implementation did not work with &lt; and &lt;= comparison,
and did not allow conditions on aggregates or grouped columns (HAVING). Fixed.. Fixed.
</li><li>Both view implementations did not work with multiple levels of nested temporary views (FROM (SELECT...)). Fixed.
</li><li>The H2 Console can now be run as a standalone web application,
or it can be embedded as a servlet into any existing web application. To build the
'H2 Console' web application, execute 'ant warConsole'.
See src/tools/org/h2/server/web and src/tools/WEB-INF for details.
This web application has been tested with Tomcat and Jetty.
</li><li>Deleting database files didn't work for Windows if the database was on the root directory of a drive.
</li><li>The Polish translation is available. Thanks a lot to Tomek!
</li><li>Windows service: the CLASSPATH was not included when starting the service. Fixed.
</li>
</ul>
<h3>Version 1.0.50 (2007-06-17)</h3><ul>
<li>File names starting with ~ are now in the user directory (Java system property user.home)
</li><li>New Console starter application uses the JDK 1.6 system tray functionality if available,
or a simple AWT frame for other platforms. To try it out, execute
java org.h2.tools.Console. Feedback is welcome.
This console starter application is not the default yet,
but the plan is to remove the SysTray tool in the future.
</li><li>New method Csv.write(Writer writer, ResultSet rs)
</li><li>If a Reader or InputStream of a LOB is not closed, the LOB can not be deleted (embedded mode only).
The exception is typically 'Error while renaming file'). As a workaround, set the system property
'h2.lobCloseBetweenReads' to true to close the LOB files between read operations.
However this slows down reading.
</li><li>Server mode: the server stack trace was included in SQLException messages. Fixed.
</li><li>Views support has been partially re-implemented. Views are up to 6 times faster.
Compared to regular queries, only 20% overhead. Because this is a bigger change,
it is not enabled by default. To enable it, set the system property 'h2.indexNew' to true
(java -Dh2.indexNew=true ..., or in source code Constants.INDEX_NEW = true).
If no problems are found, this will be enabled by default in the next release.
</li><li>In INSERT and MERGE statements, each column may only be specified once now.
</li><li>For most IOExceptions now the file name is included in the error message.
</li><li>A java.util.Date object is now converted to a TIMESTAMP in the JDBC API. Previously it was converted to a DATE.
</li><li>After calling SHUTDOWN and closing the connection and a superfluous error message appeared in the trace file. Fixed.
</li><li>In many situations, views did not use an index if they could have. Fixed. Also the explain plan for views works now.
</li><li>The table id (important for LOB files) is now included in INFORMATION_SCHEMA.TABLES.
</li><li>When using DISTINCT, ORDER BY a function works now as long as it is in the column list.
</li><li>Support for the data type CHAR. The difference to VARCHAR is: trailing spaces are ignored. This
data type is supported for compatibility with other databases and older applications.
</li><li>The aggregate function COUNT(...) now returns a long instead of an int.
</li><li>The 'ordering' of data types was not always correct, for example an operation involving REAL and DOUBLE produced a result of type REAL. Fixed.
</li><li>CSV tool: If the same instance was used for reading and writing, the tool wrote the column names twice. Fixed.
</li><li>Compatibility: Support for the data type notation CHARACTER VARYING.
</li><li>Can now ORDER BY -1 (meaning order by first column, descending), and ORDER BY ? (parameterized column number).
</li><li>Databases with invalid linked tables (for example, because the target database is not accessible) can now be opened.
Old table links don't work however.
</li><li>There was a small memory leak in the trace module. One object per opened connection was kept in a hash map.
</li><li>Linked tables can now emit UPDATE statements if 'EMIT UPDATES' is specified in the CREATE LINKED
TABLE statement. So far, updating a row always deleted the old row and then inserted the new row.
</li><li>In the last release, the H2 Console opened two connection when logging into a database,
and only closed one connection when logging out. Fixed.
</li><li>New functions LEAST and GREATEST to get the smallest or largest value from a list.
</li>
</ul>
<h3>Version 1.0.46 (2007-04-29)</h3><ul>
<li>Unnamed private in-memory database (jdbc:h2:mem:) were not 'private' as documented. Fixed.
</li><li>Autocomplete in the Console application: now the result frame scrolls to the top when the list is updated.
</li><li>GROUP BY expressions did not work correctly in subqueries. Fixed.
</li><li>New function TABLE to define ad-hoc (temporary) tables in a query.
This also solves problems with variable-size IN(...) queries:
instead of SELECT * FROM TEST WHERE ID IN(?, ?, ...) you can now write:
SELECT * FROM TABLE(ID INT=?) X, TEST WHERE X.ID=TEST.ID
In this case, the index is used.
</li><li>New data type ARRAY. Actually it was there before, but is now documented
and better tested (however it must still be considered experimental).
The java.sql.Array implementation is incomplete, but setObject(1, new Object[]{...})
and getObject(..) can be used. New functions ARRAY_GET and ARRAY_LENGTH.
</li><li>SimpleResultSet now has some basic data type conversion features.
</li><li>When using JDK 1.5 or later, and switching on h2.lobFilesInDirectories,
the performance for creating LOBs was bad. This has been fixed, however
creating lots of LOBs it is still faster when the setting is switched off.
</li><li>A problem with multiple unnamed dynamic tables (FROM (SELECT...)) has been fixed.
</li><li>Appending 'Z' to a timestamp did not have an effect. Now it is interpreted as +00:00 (GMT).
</li><li>The BACKUP command is better tested and documented.
This means hot backup (online backup) is now possible.
</li><li>The old 'Backup' tool is now called 'Script' (as the SQL statement).
</li><li>There are new 'Backup' and 'Restore' tools that work with database files directly.
</li><li>The complete syntax for referential and check constraints is now supported
when written as part of the column definition, behind PRIMARY KEY.
</li><li>CASE WHEN ... returned the wrong result when the condition evaluated to NULL.
</li><li>The new function LINK_SCHEMA simplifies linking all tables of a schema.
</li><li>SCRIPT DROP now also drops aliases (Java functions) if they exist.
</li><li>For encrypted databases, the trace option can no longer be enabled manually by creating a file.
</li><li>For linked tables, NULL in the unique key is now supported.
</li><li>For read-only databases, temp files are now created in the default temp directory instead
of the database directory.
</li><li>Sending CLOB data was slow in some systems when using the server version. Fixed.
</li><li>CSVWRITE now returns the number of rows written.
</li><li>The data type of NULLIF was NULL if the first expression was a column. Now the data type is set correctly.
</li><li>Indexes (and other related objects) for local temporary tables where not dropped
when the session was closed. Fixed.
</li><li>ALTER TABLE did not work for tables with computed columns.
</li><li>SQLException.getCause of the now works for JDK 1.4 and higher.
</li><li>If the index file was deleted, an error was logged in the .trace.db file. This is no longer done.
</li><li>The Portuguese (Europe) translation is available. Thanks a lot to Antonio Casqueiro!
</li><li>The error message for invalid views has been improved (the root cause is included in the message now).
</li><li>IN(SELECT ...) was not working correctly if the subquery returned a NULL value. Fixed.
</li><li>DROP ALL OBJECTS did not drop constants.
</li><li>DROP ALL OBJECTS dropped the role PUBLIC, which was wrong. Fixed.
</li><li>CASE was parsed as a function if the expression was in (). Fixed.
</li><li>When ORDER BY was used together with DISTINCT, it was required to type the column
name exactly in the select list and the order list exactly in the same way.
This is not required any longer.
</li></ul>
<h3>Version 1.0.44 (2007-03-04)</h3><ul>
<li>System sequences (automatically created sequences for IDENTITY or AUTO_INCREMENT columns) are now
random (UUIDs) to avoid clashes when merging databases using RUNSCRIPT.
</li><li>The precision for linked tables was not correct for some data types, for example VARCHAR. Fixed.
</li><li>Many problems and bugs in the XA support (package javax.sql) have been fixed.
</li><li>Now the server tool (org.h2.tools.Server) terminates with an exit code if a problem occured.
</li><li>The JDBC driver is now loaded if the JdbcDataSource class is loaded.
</li><li>After renaming a user the password becomes invalid. This is now documented.
</li><li>XAResource.recover didn't work. Fixed.
</li><li>XAResource.recover did throw an exception with the code XAER_OUTSIDE if there
was no connection. Now the code is XAER_RMERR.
</li><li>SCRIPT did not work correctly with BLOB or CLOB data. Fixed.
</li><li>BACKUP TO 'test.zip' now works with encrypted databases and CLOB and BLOB data.
</li><li>The function CASE WHEN ... didn't convert the returned value to the same data type,
resulting in unexpected behavior in many cases. Fixed.
</li><li>Truncating a table is now allowed if the table references another table
(but still not allowed if the table is references by another table).
</li><li>ORDER BY picked the wrong column if the same column name (but with a different table name)
was used twice in the select list.
</li><li>When a subquery was used in the select list of a query, and GROUP BY was used at the same time,
a NullPointerException could occur. Fixed.
</li><li>ORDER BY did not work when DISTINCT was used at the same time in some situations. Fixed.
</li><li>When using IN(...) on a case insensitive column (VARCHAR_IGNORECASE),
an incorrect optimization was made and the result was wrong sometimes.
</li></ul>
<h3>Version 1.0.41 (2007-01-30)</h3><ul>
<li>Experimental online backup feature using the SQL statement BACKUP TO 'fileName'.
This creates a backup in the form of a zip file. Unlike the SCRIPT TO command, the data tables are not locked.
</li><li>When using the server mode, temporary files for large LOB values are now deleted when the result set is closed.
This also means that LOBs become unavailable after closing the result, however this is according to the specs.
</li><li>It was possible that SUM throws a class cast exception if the parameter was a conditional expression.
</li><li>Benchmark: Added a multi-client test case, BenchB (similar to TPC-B).
</li><li>Compatibility: SCHEMA_NAME.SEQUENCE_NAME.NEXTVAL now works as expected.
</li><li>The Console is now translated to Hungarian thanks to Andras Hideg,
and to Indonesian thanks to Joko Yuliantoro
</li><li>XAConnection: A NullPointerException was thrown if addConnectionEventListener was called before opening the connection.
</li><li>In case the result set of a subquery was re-used, an exception was throws if the subquery result did not fit in memory.
Now the result is not re-used in this case. Generally, large subqueries should be avoided for performance reasons.
</li><li>The command "drop all objects delete files" did not work on linux if the database name was lower case.
</li><li>When setting the URL to an empty string the DataSource now throws an better exception.
</li><li>Parsing of LIKE .. ESCAPE did not stop at the expected point. Fixed.
</li><li>Can now use UUID columns as generated key values. However, the UUID column must be the primary key.
</li><li>Improved the Javadoc documentation. Now unsupported features are marked with [Not supported],
and partially supported features are [Partially supported].
</li><li>The forum subscriptions (the emails sent from the forum) now works.
</li></ul>
<h3>Version 1.0.40 (2007-01-17)</h3><ul>
<li>Setting the collation (SET COLLATOR) was very slow on some systems (up to 24 seconds).
Thanks a lot to Martina Nissler for finding this problem!
</li><li>The Console is now translated to Japanese thanks to IKEMOTO, Masahiro (ikeyan (at) arizona (dot) ne (dot) jp)
</li><li>The database engine can now be compiled with JDK 1.3 using ant codeswitch.
There are still some limitations, and the ant script to build the jar does not work yet.
</li><li>Fixed a problem where data in the log file was not written to the data file (recovery failure) after a crash,
if an index was deleted previously.
</li><li>SCRIPT NODATA now writes the row count for each table (this simplifies comparing databases).
</li><li>Selecting a column using the syntax schemaName.tableName.columnName did not work in all cases.
</li><li>Can now parse timestamps with timezone information (Z or +/-hh:mm) and dates before year 1.
However dates before year 1 are not formatted correctly (this is a Java problem).
</li><li>When stopping the TCP server from an application and immediately afterwards staring it again
using a different TCP password, an exception was thrown sometimes.
</li><li>Now PreparedStatement.setBigDecimal(..) can only be called with an object
of type java.math.BigDecimal. Derived classes are not allowed any more. Many thanks to
Maciej Wegorkiewicz for finding this problem.
</li><li>It was possible to manipulate values in the byte array after calling PreparedStatement.setBytes, and this
could lead to problems if the same byte array was used again. Now the byte array is copied if required.
</li><li>Date, time and timestamp objects were cloned in cases where it was not required. Fixed.
</li></ul>
<h3>Version 1.0.36 (2007-01-02)</h3><ul>
<li>It was possible to drop the sequence of a temporary tables with DROP ALL OBJECTS, resulting in a null pointer exception afterwards.
</li><li>Prepared statements with non-constant functions such as CURRENT_TIMESTAMP() did not get re-evaluated if the result of the function changed. Fixed.
</li><li>The (relative or absolute) directory where the script files are stored or read can now be changed using the system property h2.scriptDirectory
</li><li>Client trace files now created in the directory 'trace.db' and no longer the application directory.
This can be changed using the system property h2.clientTraceDirectory.
</li><li>In some situations the log file got corrupt if the process was terminated while the database was opening.
</li><li>Using ;RECOVER=1 in the database URL threw a syntax exception. Fixed.
</li><li>If a CLOB or BLOB was deleted in a transaction and the database crashed before the transaction was committed or rolled back,
the object was lost if it was large. Fixed.
</li><li>Now using ant-build.properties. The jdk is automatically updated when using ant codeswitch...
</li><li>Cluster: Now the server can detect if a query is read-only, and in this case the result is only read from the first cluster node.
However, there is currently no load balancing made to avoid problems with transactions / locking.
</li><li>Many settings are now initialized from system properties and can be changed on the command line without having
recompile the database. See Advances / Settings Read from System Properties.
</li><li>H2 is now available in Maven. The groupId is com.h2database, the artifactId h2 and the version 1.0.20061217.
To create the maven artifacts yourself, use 'ant mavenUploadLocal' and 'ant mavenBuildCentral'.
</li></ul>
<h3>Version 1.0.25 (2006-08-31)</h3><ul>
<li>
In some situations, wide b-tree indexes (with large VARCHAR columns for example) could get corrupted. Fixed.
</li><li>
ORDER BY was broken in the last release when using table aliases. Fixed.
</li></ul>
<h3>Version 0.9 (2005-12-13)</h3><ul>
<li>
First public release.
</li></ul>
<br /><a name="roadmap"></a> <br /><a name="roadmap"></a>
<h2>Roadmap</h2> <h2>Roadmap</h2>
<h3>Highest Priority</h3> The current roadmap is available here:
<ul> <a href="http://groups.google.com/group/h2-database/web/roadmap">
<li>Improve test code coverage http://groups.google.com/group/h2-database/web/roadmap
</li><li>More fuzz tests </a>
</li><li>Test very large databases and LOBs (up to 256 GB)
</li><li>Test multi-threaded in-memory db access
</li></ul>
<h3>In Version 1.1</h3>
<ul>
<li>Add version number. Install directory: h2-1.0, jar file: h2-1.0.jar. Micro version: use build number, staring with 1.1.100
</li><li>Automatic upgrade if there is a file format change
</li><li>ALTER TABLE on a table with a LOB could result in 'Cannot delete file' on some systems. Fixed.
</li><li>Change Constants.DEFAULT_MAX_MEMORY_UNDO to 10000 (and change the docs). Test.
</li><li>Enable and document optimizations, LOB files in directories
</li><li>Special methods for DataPage.writeByte / writeShort and so on
</li><li>Index organized tables CREATE TABLE...(...) ORGANIZATION INDEX (store in data file) (probably file format changes are required for rowId)
</li><li>Change the default for NULL || 'x' to NULL
</li></ul>
<h3>Priority 1</h3>
<ul>
<li>MVCC (Multi Version Concurrency Control)
</li><li>Read-only databases inside a jar (splitting large files to speed up random access)
</li><li>RECOVER=1 should automatically recover, =2 should run the recovery tool if required
</li><li>More tests with MULTI_THREADED=1
</li><li>Test with Spatial DB in a box / JTS (http://docs.codehaus.org/display/GEOS/SpatialDBBox)
</li><li>Document how to use H2 with PHP (generic database API)
</li><li>Optimization: result set caching (like MySQL)
</li><li>Server side cursors
</li><li>Row level locking
</li><li>System table: open sessions and locks of a database
</li><li>Function in management db: list open connections and databases of a (TCP) server
</li><li>Fix right outer joins
</li><li>Full outer joins
</li><li>Long running queries / errors / trace system table
</li><li>Migrate database tool (also from other database engines)
</li><li>Shutdown compact
</li><li>Optimization of distinct with index: select distinct name from test
</li><li>Document server mode, embedded mode, web app mode, dual mode (server+embedded)
</li><li>Stop the server: close all open databases first
</li><li>SET variable { TO | = } { value | 'value' | DEFAULT }
</li><li>Running totals: select @running:=if(@previous=t.ID,@running,0)+t.NUM as TOTAL, @previous:=t.ID
</li><li>Better support large transactions, large updates / deletes: use less memory
</li><li>Better support large transactions, large updates / deletes: allow tables without primary key
</li><li>Support Oracle RPAD and LPAD(string, n[, pad]) (truncate the end if longer)
</li><li>Procedural language / script language (Javascript)
</li></ul>
<h3>Priority 2</h3>
<ul>
<li>Updatable result sets: DatabaseMetaData.ownUpdatesAreVisible = true (for insert, delete, update)
Simple solution: automatically calls 'refresh' when the result was changed.
Compare with other databases.
</li><li>Allow editing NULL values in the Console
</li><li>Support OSGi: http://oscar-osgi.sourceforge.net, http://incubator.apache.org/felix/index.html
</li><li>Change LOB mechanism (less files, keep index of lob files, point to files and row, delete unused files earlier, maybe bundle files into a tar file)
</li><li>Set the database in an 'exclusive' mode (restrict to one user at a time)
</li><li>Clustering: recovery needs to becomes fully automatic. Global write lock feature.
</li><li>Deferred integrity checking (DEFERRABLE INITIALLY DEFERRED)
</li><li>Groovy Stored Procedures (http://groovy.codehaus.org/Groovy+SQL)
</li><li>System table / function: cache usage
</li><li>Add a migration guide (list differences between databases)
</li><li>Optimization: automatic index creation suggestion using the trace file?
</li><li>Compression performance: don't allocate buffers, compress / expand in to out buffer
</li><li>Connection pool manager
</li><li>Implement Statement.cancel for server connections
</li><li>Start / stop server with database URL
</li><li>Rebuild index functionality (other than delete the index file)
</li><li>Don't use deleteOnExit (bug 4513817: File.deleteOnExit consumes memory)
</li><li>Console: add accesskey to most important commands (A, AREA, BUTTON, INPUT, LABEL, LEGEND, TEXTAREA)
</li><li>Feature: a setting to delete the the log or not (for backup)
</li><li>Test with Sun ASPE1_4; JEE Sun AS PE1.4
</li><li>Test performance again with SQL Server, Oracle, DB2
</li><li>Test with dbmonster (http://dbmonster.kernelpanic.pl/)
</li><li>Test with dbcopy (http://dbcopyplugin.sourceforge.net)
</li><li>Find a tool to view a text file >100 MB, with find, page up and down (like less)
</li><li>Implement, test, document XAConnection and so on
</li><li>Web site: meta keywords, description, get rid of frame set
</li><li>Pluggable data type (for compression, validation, conversion, encryption)
</li><li>CHECK: find out what makes CHECK=TRUE slow, move to CHECK2
</li><li>Improve recovery: improve code for log recovery problems (less try/catch)
</li><li>Log linear hash index changes, fast open / close
</li><li>Index usage for (ID, NAME)=(1, 'Hi'); document
</li><li>Suggestion: include jetty as Servlet Container (like LAMP)
</li><li>Trace shipping to server
</li><li>Performance / server mode: use UDP optionally?
</li><li>Version check: docs / web console (using javascript), and maybe in the library (using TCP/IP)
</li><li>Aggregates: support MEDIAN
</li><li>Web server classloader: override findResource / getResourceFrom
</li><li>Cost for embedded temporary view is calculated wrong, if result is constant
</li><li>Comparison: pluggable sort order: natural sort
</li><li>Count index range query (count(*) where id between 10 and 20)
</li><li>Eclipse plugin
</li><li>iReport to support H2
</li><li>Implement missing JDBC API (CallableStatement,...)
</li><li>Sequence: add features [NO] MINVALUE, MAXVALUE, CACHE, CYCLE
</li><li>Compression of the cache
</li><li>Include SMPT (mail) server (at least client) (alert on cluster failure, low disk space,...)
</li><li>Make the jar more modular
</li><li>Drop with restrict (currently cascade is the default)
</li><li>JSON parser and functions
</li><li>Option for Java functions: constant/isDeterministic to allow early evaluation when all parameters are constant
</li><li>Automatic collection of statistics (auto ANALYZE)
</li><li>Server: client ping from time to time (to avoid timeout - is timeout a problem?)
</li><li>Copy database: Tool with config GUI and batch mode, extensible (example: compare)
</li><li>Document, implement tool for long running transactions using user defined compensation statements
</li><li>Support SET TABLE DUAL READONLY
</li><li>Linked schema using CSV files: one schema for a directory of files; support indexes for CSV files
</li><li>Don't write stack traces for common exceptions like duplicate key to the log by default
</li><li>Setting for MAX_QUERY_TIME (default no limit?)
</li><li>GCJ: what is the state now?
</li><li>Convert large byte[]/Strings to streams in the JDBC API (asap).
</li><li>Use Janino to convert Java to C++
</li><li>Reduce disk space usage (Derby uses less disk space?)
</li><li>Events for: Database Startup, Connections, Login attempts, Disconnections, Prepare (after parsing), Web Server (see http://docs.openlinksw.com/virtuoso/fn_dbev_startup.html)
</li><li>Optimization: Log compression
</li><li>Compatibility: in MySQL, HSQLDB, /0.0 is NULL; in PostgreSQL, Derby: Division by zero
</li><li>Functional tables should accept parameters from other tables (see FunctionMultiReturn)
SELECT * FROM TEST T, P2C(T.A, T.R)
</li><li>Custom class loader to reload functions on demand
</li><li>Test http://mysql-je.sourceforge.net/
</li><li>Close all files when closing the database (including LOB files that are open on the client side)
</li><li>Test Connection Pool http://jakarta.apache.org/commons/dbcp
</li><li>Profiler option or profiling tool to find long running and often repeated queries (using DatabaseEventListener API)
</li><li>Function to read/write a file from/to LOB
</li><li>Allow custom settings (@PATH for RUNSCRIPT for example)
</li><li>Performance test: read the data (getString) and use column names to get the data
</li><li>EXE file: maybe use http://jsmooth.sourceforge.net
</li><li>SELECT ... FOR READ WAIT [maxMillisToWait]
</li><li>Automatically delete the index file if opening it fails
</li><li>Performance: Automatically build in-memory indexes if the whole table is in memory
</li><li>H2 Console: The webclient could support more features like phpMyAdmin.
</li><li>The HELP information schema can be directly exposed in the Console
</li><li>Maybe use the 0x1234 notation for binary fields, see MS SQL Server
</li><li>KEY_COLUMN_USAGE (http://dev.mysql.com/doc/refman/5.0/en/information-schema.html, http://www.xcdsql.org/Misc/INFORMATION_SCHEMA%20With%20Rolenames.gif)
</li><li>Support Oracle CONNECT BY in some way: http://www.adp-gmbh.ch/ora/sql/connect_by.html, http://philip.greenspun.com/sql/trees.html
</li><li>SQL 2003 (http://www.wiscorp.com/sql_2003_standard.zip)
</li><li>http://www.jpackage.org
</li><li>Version column (number/sequence and timestamp based)
</li><li>Optimize getGeneratedKey: send last identity after each execute (server).
</li><li>Date: default date is '1970-01-01' (is it 1900-01-01 in the standard / other databases?)
</li><li>Test and document UPDATE TEST SET (ID, NAME) = (SELECT ID*10, NAME || '!' FROM TEST T WHERE T.ID=TEST.ID);
</li><li>Better space re-use in the files after deleting data (shrink the files)
</li><li>Max memory rows / max undo log size: use block count / row size not row count
</li><li>Index summary is only written if log=2; maybe write it also when log=1 and everything is fine (and no in doubt transactions)
</li><li>Support 123L syntax as in Java; example: SELECT (2000000000*2)
</li><li>Implement point-in-time recovery
</li><li>Memory database: add a feature to keep named database open until 'shutdown'
</li><li>Use the directory of the first script as the default directory for any scripts run inside that script
</li><li>Include the version name in the jar file name
</li><li>Optimize IN(...), IN(select), ID=? OR ID=?: create temp table and use join
</li><li>LIKE: improved version for larger texts (currently using naive search)
</li><li>Auto-reconnect on lost connection to server (even if the server was re-started) except if autocommit was off and there was pending transaction
</li><li>The Script tool should work with other databases as well
</li><li>Automatically convert to the next 'higher' data type whenever there is an overflow.
</li><li>Throw an exception when the application calls getInt on a Long (optional)
</li><li>Default date format for input and output (local date constants)
</li><li>Cache collation keys for performance
</li><li>Convert OR condition to UNION or IN if possible
</li><li>ValueInt.convertToString and so on (remove Value.convertTo)
</li><li>Support custom Collators
</li><li>Document ROWNUM usage for reports: SELECT ROWNUM, * FROM (subquery)
</li><li>Clustering: Reads should be randomly distributed or to a designated database on RAM
</li><li>Clustering: When a database is back alive, automatically synchronize with the master
</li><li>Standalone tool to get relevant system properties and add it to the trace output.
</li><li>Support mixed clustering mode (one embedded, the other server mode)
</li><li>Support 'call proc($1=value)' (PostgreSQL, Oracle)
</li><li>HSQLDB compatibility: "INSERT INTO TEST(name) VALUES(?); SELECT IDENTITY()"
</li><li>Shutdown lock (shutdown can only start if there are no logins pending, and logins are delayed until shutdown ends)
</li><li>Automatically delete the index file if opening it fails
</li><li>DbAdapters http://incubator.apache.org/cayenne/
</li><li>JAMon (proxy jdbc driver)
</li><li>Console: Allow setting Null value; Alternative display format two column (for copy and paste as well)
</li><li>Console: Improve editing data (Tab, Shift-Tab, Enter, Up, Down, Shift+Del?)
</li><li>Console: Autocomplete Ctrl+Space inserts template
</li><li>Google Code http://code.google.com/p/h2database/issues/list#
</li><li>Simplify translation ('Donate a translation')
</li><li>Option to encrypt .trace.db file
</li><li>Improve create index performance
</li><li>Write Behind Cache on SATA leads to data corruption
See also http://sr5tech.com/write_back_cache_experiments.htm
and http://www.jasonbrome.com/blog/archives/2004/04/03/writecache_enabled.html
</li><li>Functions with unknown return or parameter data types: serialize / deserialize
</li><li>Test if idle TCP connections are closed, and how to disable that
</li><li>Try using a factory for Row, Value[] (faster?), http://javolution.org/, alternative ObjectArray / IntArray
</li><li>Auto-Update feature for database, .jar file
</li><li>ResultSet SimpleResultSet.readFromURL(String url): id varchar, state varchar, released timestamp
</li><li>RANK() and DENSE_RANK(), Partition using OVER()
</li><li>ROW_NUMBER (not the same as ROWNUM)
</li><li>Partial indexing (see PostgreSQL)
</li><li>BUILD should fail if ant test fails
</li><li>http://rubyforge.org/projects/hypersonic/
</li><li>DbVisualizer profile for H2
</li><li>Add comparator (x === y) : (x = y or (x is null and y is null))
</li><li>Try to create trace file even for read only databases
</li><li>Add a sample application that runs the H2 unit test and writes the result to a file (so it can be included in the user app)
</li><li>Count on a column that can not be null would be optimized to COUNT(*)
</li><li>Table order: ALTER TABLE TEST ORDER BY NAME DESC (MySQL compatibility)
</li><li>Backup tool should work with other databases as well
</li><li>Console: -ifExists doesn't work for the console. Add a flag to disable other dbs
</li><li>Maybe use Fowler Noll Vo hash function
</li><li>Improved full text search (supports LOBs, reader / tokenizer / filter).
</li><li>Performance: Update in-place
</li><li>Check if 'FSUTIL behavior set disablelastaccess 1' improves the performance (fsutil behavior query disablelastaccess)
</li><li>Java static code analysis: http://pmd.sourceforge.net/
</li><li>Java static code analysis: http://www.eclipse.org/tptp/
</li><li>Compatibility for CREATE SCHEMA AUTHORIZATION
</li><li>Implement Clob / Blob truncate and the remaining functionality
</li><li>Maybe close LOBs after closing connection
</li><li>Tree join functionality
</li><li>Support alter table add column if table has views defined
</li><li>Add multiple columns at the same time with ALTER TABLE .. ADD .. ADD ..
</li><li>Support trigger on the tables information_schema.tables and ...columns
</li><li>Add H2 to Gem (Ruby install system)
</li><li>API for functions / user tables
</li><li>Order conditions inside AND / OR to optimize the performance
</li><li>Support linked JCR tables
</li><li>Make sure H2 is supported by Execute Query: http://executequery.org/
</li><li>Read InputStream when executing, as late as possible (maybe only embedded mode). Problem with re-execute.
</li><li>Full text search: min word length; store word positions
</li><li>FTP Server: Implement a client to send / receive files to server (dir, get, put)
</li><li>FTP Server: Implement SFTP / FTPS
</li><li>Add an option to the SCRIPT command to generate only portable / standard SQL
</li><li>Test Dezign for Databases (http://www.datanamic.com)
</li><li>Fast library for parsing / formatting: http://javolution.org/
</li><li>Updatable Views (simple cases first)
</li><li>Support ARRAY data type
</li><li>Implement more JDBC 4.0 features
</li><li>H2 Console: implement a servlet to allow simple web app integration
</li><li>Support TRANSFORM / PIVOT as in MS Access
</li><li>Sequence: PostgreSQL compatibility (rename, create) (http://www.postgresql.org/docs/8.2/static/sql-altersequence.html)
</li><li>SELECT * FROM (VALUES (...), (...), ....) AS alias(f1, ...)
</li><li>Support updatable views with join on primary keys (to extend a table)
</li><li>File_Read / File_Store funktionen: FILE_STORE('test.sql', ?), FILE_READ('test.sql')
</li><li>Public interface for functions (not public static)
</li><li>Autocomplete: if I type the name of a table that does not exist (should say: syntax not supported)
</li><li>Autocomplete: schema support: "Other Grammar","Table Expression","{[schemaName.]tableName | (select)} [[AS] newTableAlias]
</li><li>Functions: options readonly, deterministic (pure, always return the same value)
</li><li>Document FTP server, including -ftpTask option to execute / kill remote processes
</li><li>Add jdbcx to the javadocs
</li><li>Shrink the data file without closing the database (if the end of the file is empty)
</li><li>Delay reading the row if data is not required
</li><li>Eliminate undo log records if stored on disk (just one pointer per block, not per record)
</li><li>Feature matrix like here: http://www.inetsoftware.de/products/jdbc/mssql/features/default.asp.
</li><li>Updatable result set on table without primary key or unique index
</li><li>Use LinkedList instead of ArrayList where applicable
</li><li>Optimization: (A=B AND B=C) > (A=B AND B=C AND A=C)
</li><li>Support % operator (modulo)
</li><li>Large subqueries: close them when the main query is closed, not earlier (so result can be reused)
</li><li>Support 1+'2'=3, '1'+'2'='12' (MS SQL Server compatibility)
</li><li>Support nested transactions
</li><li>Add a benchmark for big databases, and one for many users
</li><li>Compression in the result set (repeating values in the same column)
</li><li>Improve command line consistency (+/- options, or true false options)
</li><li>Allow to use the catalog name in statements: [[catalog.]schema.]object
</li><li>Support curtimestamp (like curtime, curdate)
</li><li>Support ANALYZE {TABLE|INDEX} tableName COMPUTE|ESTIMATE|DELETE STATISTICS ptnOption options
</li><li>Support Sequoia (Continuent.org)
</li><li>Dynamic length numbers / special methods for DataPage.writeByte / writeShort / Ronni Nielsen
</li><li>Pluggable tracing system, ThreadPool, (AvalonDB / deebee / Paul Hammant)
</li><li>Recursive Queries (see details)
</li><li>Use index on boolean flag (see details)
</li><li>Add build for embedded database only
</li><li>Release locks (shared or exclusive) on demand
</li><li>Support catalog names
</li><li>Add object id to metadata tables
</li><li>Support OUTER UNION
</li><li>Support Parameterized Views (similar to CSVREAD, but using just SQL for the definition)
</li><li>Implement a command line SQL utility similar to HenPlus: http://henplus.sourceforge.net
</li><li>A way (JDBC driver) to map an URL (jdbc:h2map:c1) to a connection object
</li><li>Build script for the embedded functionality only (h2embedded.jar)
</li><li>Option for SCRIPT to only process one or a set of tables, and append to a file
</li><li>Support using a unique index for IS NULL (including linked tables)
</li><li>Support linked tables to the current database
</li><li>Support dynamic linked schema (automatically adding/updating/removing tables)
</li><li>Compatibility with Derby: VALUES(1), (2); SELECT * FROM (VALUES (1), (2)) AS myTable(c1)
</li><li>Compatibility: # is the start of a single line comment (MySQL) but date quote (Access). Mode specific
</li><li>Run benchmarks with JDK 1.5, JDK 1.6, java -server
</li><li>Optimizations: Faster hash function for strings, byte arrays, big decimal
</li><li>Improve trace feature: add replay functionality
</li><li>DatabaseEventListener: callback for all operations (including expected time, RUNSCRIPT) and cancel functionality
</li><li>H2 Console / large result sets: use 'streaming' instead of building the page in-memory
</li><li>Benchmark: add a graph to show how databases scale (performance/database size)
</li><li>Implement a SQLData interface to map your data over to a custom object
</li><li>Extend H2 Console to run tools (show command line as well)
</li><li>Make DDL (Data Definition) operations transactional
</li><li>Allow execution time prepare for SELECT * FROM CSVREAD(?, 'columnNameString')
</li><li>Support multiple directories (on different hard drives) for the same database
</li><li>Server protocol: use challenge response authentication, but client sends hash(user+password) encrypted with response
</li><li>Support EXEC[UTE] (doesn't return a result set, compatible to MS SQL Server)
</li><li>GROUP BY and DISTINCT: support large groups (buffer to disk), do not keep large sets in memory
</li><li>Support native XML data type
</li><li>Support triggers with a string property or option: SpringTrigger, OSGITrigger
</li><li>Clustering: adding a node should be very fast and without interrupting clients (very short lock)
</li><li>Support materialized views (using triggers)
</li><li>Store dates in local timezone (portability of database files)
</li><li>Ability to resize the cache array when resizing the cache
</li><li>Automatic conversion from WHERE X>10 AND X>20 to X>20
</li><li>Time based cache writing (one second after writing the log)
</li><li>Write a H2 driver for http://db.apache.org/ddlutils/
</li><li>Index usage for REGEXP LIKE.
</li><li>Add a role DBA (like ADMIN).
</li><li>Automatic mode: jdbc:h2:auto: (embedded mode if possible, if not use server mode).
Problem: what to do when server stops while others are connected to it.
</li><li>Access rights: remember the owner of an object. COMMENT: allow owner of object to change it.
</li><li>Implement INSTEAD OF trigger.
</li><li>Access rights: Finer grained access control (grant access for specific functions)
</li><li>Support N'text'
</li><li>Support SCOPE_IDENTITY() to avoid problems when inserting rows in a trigger
</li><li>Support DESCRIBE like MySQL or Oracle (DESC|DESCRIBE {[schema.]object[@connect_identifier]})
</li><li>Set a connection read only (Connection.setReadOnly)
</li><li>In MySQL mode, for AUTO_INCREMENT columns, don't set the primary key
</li><li>Use JDK 1.4 file locking to create the lock file (but not yet by default); writing a system property to detect concurrent access from the same VM (different classloaders).
</li><li>Read-only sessions (Connection.setReadOnly)
</li><li>Support compatibility for jdbc:hsqldb:res:
</li><li>In the MySQL and PostgreSQL, use lower case identifiers by default (DatabaseMetaData.storesLowerCaseIdentifiers = true)
</li><li>Provide a simple, lightweight O/R mapping tool
</li><li>Provide an Java SQL builder with standard and H2 syntax
</li><li>Data compression for in-memory database
</li><li>Trace: write os, file system, vm,... when opening the database
</li><li>Trace: write dangerous operations (set log 0,...) in every case (including when opening the database)
</li><li>ParameterMetaData should return correct data type where possible (INSERT for example)
</li><li>Support indexes for views (probably requires materialized views)
</li><li>Linked tables that point to the same database should share the connection
</li><li>Use log for rollback
</li><li>Document SET SEARCH_PATH, BEGIN, EXECUTE, $ parameters
</li><li>Complete Javadocs for ErrorCode messages and add to docs
</li><li>Browser: use Desktop.isDesktopSupported and browse when using JDK 1.6
</li><li>Document org.h2.samples.MixedMode
</li><li>Server: use one listener (detect if the request comes from an PG or TCP client)
</li><li>Store dates as 'local'. Existing files use GMT. Use escape syntax for compatibility)
</li><li>Support data type INTERVAL
</li><li>NATURAL JOIN: MySQL and PostgreSQL don't repeat columns when using SELECT * ...
</li><li>Optimize SELECT MIN(ID), MAX(ID), COUNT(*) FROM TEST WHERE ID BETWEEN 100 AND 200
</li><li>Support Oracle functions: TRUNC, NVL2, TO_CHAR, TO_DATE, TO_NUMBER
</li><li>Support setQueryTimeout (using System.currentTimeMillis in a loop; not using a thread)
</li><li>Support large updates and deletes (currently all rows are loaded into memory)
</li></ul>
<h3>Not Planned</h3> <h3>Not Planned</h3>
<ul> <ul>
<li>HSQLDB (did) support this: select id i from test where i>0 (other databases don't) <li>HSQLDB does/did support this: select id i from test where i>0 (other databases don't)
</li><li>String.intern (so that Strings can be compared with ==) will not be used because some VMs have problems when used extensively </li><li>String.intern (so that Strings can be compared with ==) will not be used because some VMs have problems when used extensively
</li></ul> </li></ul>
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.tools.net;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* This class helps debug the PostgreSQL network protocol.
* It listens on one port, and sends the exact same data to another port.
*/
public class PgTcpRedirect {
public static void main(String[] args) throws Exception {
new PgTcpRedirect().loop(args);
}
void loop(String[] args) throws Exception {
// MySQL protocol:
// http://www.redferni.uklinux.net/mysql/MySQL-Protocol.html
// PostgreSQL protocol:
// http://developer.postgresql.org/pgdocs/postgres/protocol.html
// int portServer = 9083, portClient = 9084;
// int portServer = 3306, portClient = 3307;
// int portServer = 5435, portClient = 5433; // H2 PgServer
int portServer = 5432, portClient = 5433; // PostgreSQL
for (int i = 0; i < args.length; i++) {
if ("-client".equals(args[i])) {
portClient = Integer.parseInt(args[++i]);
} else if ("-server".equals(args[i])) {
portServer = Integer.parseInt(args[++i]);
}
}
ServerSocket listener = new ServerSocket(portClient);
while (true) {
Socket client = listener.accept();
Socket server = new Socket("localhost", portServer);
TcpRedirectThread c = new TcpRedirectThread(client, server, true);
TcpRedirectThread s = new TcpRedirectThread(server, client, false);
new Thread(c).start();
new Thread(s).start();
}
}
private class TcpRedirectThread implements Runnable {
private Socket read, write;
private int state;
private boolean client;
private static final int STATE_INIT_CLIENT = 0, STATE_REGULAR = 1;
TcpRedirectThread(Socket read, Socket write, boolean client) {
this.read = read;
this.write = write;
this.client = client;
state = client ? STATE_INIT_CLIENT : STATE_REGULAR;
}
String readStringNull(InputStream in) throws IOException {
StringBuffer buff = new StringBuffer();
while (true) {
int x = in.read();
if (x <= 0) {
break;
}
buff.append((char) x);
}
return buff.toString();
}
private void println(String s) {
// System.out.println(s);
}
private boolean processClient(InputStream inStream, OutputStream outStream) throws IOException {
DataInputStream dataIn = new DataInputStream(inStream);
ByteArrayOutputStream buff = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(buff);
if (state == STATE_INIT_CLIENT) {
state = STATE_REGULAR;
int len = dataIn.readInt();
dataOut.writeInt(len);
len -= 4;
byte[] data = new byte[len];
dataIn.readFully(data, 0, len);
dataOut.write(data);
dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len));
int version = dataIn.readInt();
if (version == 80877102) {
println("CancelRequest");
println(" pid: " + dataIn.readInt());
println(" key: " + dataIn.readInt());
} else if (version == 80877103) {
println("SSLRequest");
} else {
println("StartupMessage");
println(" version " + version + " (" + (version >> 16) + "." + (version & 0xff) + ")");
while (true) {
String param = readStringNull(dataIn);
if (param.length() == 0) {
break;
}
String value = readStringNull(dataIn);
println(" param " + param + "=" + value);
}
}
} else {
int x = dataIn.read();
if (x < 0) {
println("end");
return false;
}
// System.out.println(" x=" + (char)x+" " +x);
dataOut.write(x);
int len = dataIn.readInt();
dataOut.writeInt(len);
len -= 4;
byte[] data = new byte[len];
dataIn.readFully(data, 0, len);
dataOut.write(data);
dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len));
switch (x) {
case 'B': {
println("Bind");
println(" destPortal: " + readStringNull(dataIn));
println(" prepName: " + readStringNull(dataIn));
int formatCodesCount = dataIn.readShort();
for (int i = 0; i < formatCodesCount; i++) {
println(" formatCode[" + i + "]=" + dataIn.readShort());
}
int paramCount = dataIn.readShort();
for (int i = 0; i < paramCount; i++) {
int paramLen = dataIn.readInt();
println(" length[" + i + "]=" + paramLen);
byte[] d2 = new byte[paramLen];
dataIn.readFully(d2);
}
int resultCodeCount = dataIn.readShort();
for (int i = 0; i < resultCodeCount; i++) {
println(" resultCodeCount[" + i + "]=" + dataIn.readShort());
}
break;
}
case 'C': {
println("Close");
println(" type: (S:prepared statement, P:portal): " + dataIn.read());
break;
}
case 'd': {
println("CopyData");
break;
}
case 'c': {
println("CopyDone");
break;
}
case 'f': {
println("CopyFail");
println(" message: " + readStringNull(dataIn));
break;
}
case 'D': {
println("Describe");
println(" type (S=prepared statement, P=portal): " + (char) dataIn.readByte());
println(" name: " + readStringNull(dataIn));
break;
}
case 'E': {
println("Execute");
println(" name: " + readStringNull(dataIn));
println(" maxRows: " + dataIn.readShort());
break;
}
case 'H': {
println("Flush");
break;
}
case 'F': {
println("FunctionCall");
println(" objectId:" + dataIn.readInt());
int columns = dataIn.readShort();
for (int i = 0; i < columns; i++) {
println(" formatCode[" + i + "]: " + dataIn.readShort());
}
int count = dataIn.readShort();
for (int i = 0; i < count; i++) {
int l = dataIn.readInt();
println(" len[" + i + "]: " + l);
if (l >= 0) {
for (int j = 0; j < l; j++) {
dataIn.readByte();
}
}
}
println(" resultFormat: " + dataIn.readShort());
break;
}
case 'P': {
println("Parse");
println(" name:" + readStringNull(dataIn));
println(" query:" + readStringNull(dataIn));
int count = dataIn.readShort();
for (int i = 0; i < count; i++) {
println(" [" + i + "]: " + dataIn.readInt());
}
break;
}
case 'p': {
println("PasswordMessage");
println(" password: " + readStringNull(dataIn));
break;
}
case 'Q': {
println("Query");
println(" sql : " + readStringNull(dataIn));
break;
}
case 'S': {
println("Sync");
break;
}
case 'X': {
println("Terminate");
break;
}
default:
println("############## UNSUPPORTED: " + (char) x);
}
}
dataOut.flush();
byte[] buffer = buff.toByteArray();
printData(buffer, buffer.length);
try {
outStream.write(buffer, 0, buffer.length);
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
private boolean processServer(InputStream inStream, OutputStream outStream) throws IOException {
DataInputStream dataIn = new DataInputStream(inStream);
ByteArrayOutputStream buff = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(buff);
int x = dataIn.read();
if (x < 0) {
println("end");
return false;
}
// System.out.println(" x=" + (char)x+" " +x);
dataOut.write(x);
int len = dataIn.readInt();
dataOut.writeInt(len);
len -= 4;
byte[] data = new byte[len];
dataIn.readFully(data, 0, len);
dataOut.write(data);
dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len));
switch (x) {
case 'R': {
println("Authentication");
int value = dataIn.readInt();
if (value == 0) {
println(" Ok");
} else if (value == 2) {
println(" KerberosV5");
} else if (value == 3) {
println(" CleartextPassword");
} else if (value == 4) {
println(" CryptPassword");
byte b1 = dataIn.readByte();
byte b2 = dataIn.readByte();
println(" salt1=" + b1 + " salt2=" + b2);
} else if (value == 5) {
println(" MD5Password");
byte b1 = dataIn.readByte();
byte b2 = dataIn.readByte();
byte b3 = dataIn.readByte();
byte b4 = dataIn.readByte();
println(" salt1=" + b1 + " salt2=" + b2 + " 3=" + b3 + " 4=" + b4);
} else if (value == 6) {
println(" SCMCredential");
}
break;
}
case 'K': {
println("BackendKeyData");
println(" process ID " + dataIn.readInt());
println(" key " + dataIn.readInt());
break;
}
case '2': {
println("BindComplete");
break;
}
case '3': {
println("CloseComplete");
break;
}
case 'C': {
println("CommandComplete");
println(" command tag: " + readStringNull(dataIn));
break;
}
case 'd': {
println("CopyData");
break;
}
case 'c': {
println("CopyDone");
break;
}
case 'G': {
println("CopyInResponse");
println(" format: " + dataIn.readByte());
int columns = dataIn.readShort();
for (int i = 0; i < columns; i++) {
println(" formatCode[" + i + "]: " + dataIn.readShort());
}
break;
}
case 'H': {
println("CopyOutResponse");
println(" format: " + dataIn.readByte());
int columns = dataIn.readShort();
for (int i = 0; i < columns; i++) {
println(" formatCode[" + i + "]: " + dataIn.readShort());
}
break;
}
case 'D': {
println("DataRow");
int columns = dataIn.readShort();
println(" columns : " + columns);
for (int i = 0; i < columns; i++) {
int l = dataIn.readInt();
if (l > 0) {
for (int j = 0; j < l; j++) {
dataIn.readByte();
}
}
// println(" ["+i+"] len: " + l);
}
break;
}
case 'I': {
println("EmptyQueryResponse");
break;
}
case 'E': {
println("ErrorResponse");
while (true) {
int fieldType = dataIn.readByte();
if (fieldType == 0) {
break;
}
String msg = readStringNull(dataIn);
// http://developer.postgresql.org/pgdocs/postgres/protocol-error-fields.html
// S Severity
// C Code: the SQLSTATE code
// M Message
// D Detail
// H Hint
// P Position
// p Internal position
// q Internal query
// W Where
// F File
// L Line
// R Routine
println(" fieldType: " + fieldType + " msg: " + msg);
}
break;
}
case 'V': {
println("FunctionCallResponse");
int resultLen = dataIn.readInt();
println(" len: " + resultLen);
break;
}
case 'n': {
println("NoData");
break;
}
case 'N': {
println("NoticeResponse");
while (true) {
int fieldType = dataIn.readByte();
if (fieldType == 0) {
break;
}
String msg = readStringNull(dataIn);
// http://developer.postgresql.org/pgdocs/postgres/protocol-error-fields.html
// S Severity
// C Code: the SQLSTATE code
// M Message
// D Detail
// H Hint
// P Position
// p Internal position
// q Internal query
// W Where
// F File
// L Line
// R Routine
println(" fieldType: " + fieldType + " msg: " + msg);
}
break;
}
case 'A': {
println("NotificationResponse");
println(" processID: " + dataIn.readInt());
println(" condition: " + readStringNull(dataIn));
println(" information: " + readStringNull(dataIn));
break;
}
case 't': {
println("ParameterDescription");
println(" processID: " + dataIn.readInt());
int count = dataIn.readShort();
for (int i = 0; i < count; i++) {
println(" [" + i + "] objectId: " + dataIn.readInt());
}
break;
}
case 'S': {
println("ParameterStatus");
println(" parameter " + readStringNull(dataIn) + " = " + readStringNull(dataIn));
break;
}
case '1': {
println("ParseComplete");
break;
}
case 's': {
println("ParseComplete");
break;
}
case 'Z': {
println("ReadyForQuery");
println(" status (I:idle, T:transaction, E:failed): " + (char) dataIn.readByte());
break;
}
case 'T': {
println("RowDescription");
int columns = dataIn.readShort();
println(" columns : " + columns);
for (int i = 0; i < columns; i++) {
println(" [" + i + "]");
println(" name:" + readStringNull(dataIn));
println(" tableId:" + dataIn.readInt());
println(" columnId:" + dataIn.readShort());
println(" dataTypeId:" + dataIn.readInt());
println(" dataTypeSize (pg_type.typlen):" + dataIn.readShort());
println(" modifier (pg_attribute.atttypmod):" + dataIn.readInt());
println(" format code:" + dataIn.readShort());
}
break;
}
default:
println("############## UNSUPPORTED: " + (char) x);
}
dataOut.flush();
byte[] buffer = buff.toByteArray();
printData(buffer, buffer.length);
try {
outStream.write(buffer, 0, buffer.length);
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public void run() {
try {
OutputStream out = write.getOutputStream();
InputStream in = read.getInputStream();
while (true) {
if (client) {
} else {
}
boolean more;
if (client) {
more = processClient(in, out);
} else {
more = processServer(in, out);
}
if (!more) {
break;
}
}
try {
read.close();
} catch (IOException e) {
}
try {
write.close();
} catch (IOException e) {
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private synchronized void printData(byte[] buffer, int len) {
// System.out.print(" ");
// for(int i=0; i<len; i++) {
// int c = buffer[i] & 255;
// if(c >= ' ' && c <= 127 && c != '[' & c != ']') {
// System.out.print((char)c);
// } else {
// System.out.print("[" + Integer.toHexString(c) + "]");
// }
// }
// System.out.println();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论