提交 cd697858 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 37d91a6f
...@@ -728,27 +728,29 @@ INFORMATION_SCHEMA.SETTINGS ...@@ -728,27 +728,29 @@ INFORMATION_SCHEMA.SETTINGS
<th>Description</th></tr> <th>Description</th></tr>
<tr><td>h2.check</td><td>true</td><td>Assertions in the database engine</td></tr> <tr><td>h2.check</td><td>true</td><td>Assertions in the database engine</td></tr>
<tr><td>h2.check2</td><td>false</td><td>Additional assertions</td></tr> <tr><td>h2.check2</td><td>false</td><td>Additional assertions</td></tr>
<tr><td>h2.clientTraceDirectory</td><td>trace.db/</td><td>Directory where the trace files of the JDBC client are stored (only for client / server)</td></tr>
<tr><td>h2.emergencySpaceInitial</td><td>1048576</td><td>Size of 'reserve' file to detect disk full problems early</td></tr>
<tr><td>h2.emergencySpaceMin</td><td>131072</td><td>Minimum size of 'reserve' file</td></tr>
<tr><td>h2.lobCloseBetweenReads</td><td>false</td><td>Close LOB files between read operations</td></tr>
<tr><td>h2.lobFilesInDirectories</td><td>false</td><td>Store LOB files in subdirectories</td></tr> <tr><td>h2.lobFilesInDirectories</td><td>false</td><td>Store LOB files in subdirectories</td></tr>
<tr><td>h2.lobFilesPerDirectory</td><td>256</td><td>Maximum number of LOB files per directory</td></tr> <tr><td>h2.lobFilesPerDirectory</td><td>256</td><td>Maximum number of LOB files per directory</td></tr>
<tr><td>h2.logAllErrors</td><td>false</td><td>Write stack traces of any kind of error to a file</td></tr>
<tr><td>h2.logAllErrorsFile</td><td>h2errors.txt</td><td>File name to log errors</td></tr>
<tr><td>h2.maxFileRetry</td><td>16</td><td>Number of times to retry file delete and rename</td></tr>
<tr><td>h2.multiThreadedKernel</td><td>false</td><td>Allow multiple sessions to run concurrently</td></tr> <tr><td>h2.multiThreadedKernel</td><td>false</td><td>Allow multiple sessions to run concurrently</td></tr>
<tr><td>h2.runFinalizers</td><td>true</td><td>Run finalizers to detect unclosed connections</td></tr> <tr><td>h2.objectCache</td><td>true</td><td>Cache commonly used objects (integers, strings)</td></tr>
<tr><td>h2.optimizeMinMax</td><td>true</td><td>Optimize MIN and MAX aggregate functions</td></tr> <tr><td>h2.objectCacheMaxPerElementSize</td><td>4096</td><td>Maximum size of an object in the cache</td></tr>
<tr><td>h2.objectCacheSize</td><td>1024</td><td>Size of object cache</td></tr>
<tr><td>h2.optimizeIn</td><td>true</td><td>Optimize IN(...) comparisons</td></tr> <tr><td>h2.optimizeIn</td><td>true</td><td>Optimize IN(...) comparisons</td></tr>
<tr><td>h2.redoBufferSize</td><td>262144</td><td>Size of the redo buffer (used at startup when recovering)</td></tr> <tr><td>h2.optimizeMinMax</td><td>true</td><td>Optimize MIN and MAX aggregate functions</td></tr>
<tr><td>h2.recompileAlways</td><td>false</td><td>Always recompile prepared statements</td></tr>
<tr><td>h2.optimizeSubqueryCache</td><td>true</td><td>Cache subquery results</td></tr> <tr><td>h2.optimizeSubqueryCache</td><td>true</td><td>Cache subquery results</td></tr>
<tr><td>h2.overflowExceptions</td><td>true</td><td>Throw an exception on integer overflows</td></tr> <tr><td>h2.overflowExceptions</td><td>true</td><td>Throw an exception on integer overflows</td></tr>
<tr><td>h2.logAllErrors</td><td>false</td><td>Write stack traces of any kind of error to a file</td></tr> <tr><td>h2.recompileAlways</td><td>false</td><td>Always recompile prepared statements</td></tr>
<tr><td>h2.logAllErrorsFile</td><td>h2errors.txt</td><td>File name to log errors</td></tr> <tr><td>h2.redoBufferSize</td><td>262144</td><td>Size of the redo buffer (used at startup when recovering)</td></tr>
<tr><td>h2.runFinalizers</td><td>true</td><td>Run finalizers to detect unclosed connections</td></tr>
<tr><td>h2.scriptDirectory</td><td></td><td>Relative or absolute directory where the script files are stored to or read from</td></tr>
<tr><td>h2.serverCachedObjects</td><td>64</td><td>TCP Server: number of cached objects per session</td></tr> <tr><td>h2.serverCachedObjects</td><td>64</td><td>TCP Server: number of cached objects per session</td></tr>
<tr><td>h2.serverSmallResultSetSize</td><td>100</td><td>TCP Server: result sets below this size are sent in one block</td></tr> <tr><td>h2.serverSmallResultSetSize</td><td>100</td><td>TCP Server: result sets below this size are sent in one block</td></tr>
<tr><td>h2.emergencySpaceInitial</td><td>1048576</td><td>Size of 'reserve' file to detect disk full problems early</td></tr>
<tr><td>h2.emergencySpaceMin</td><td>131072</td><td>Minimum size of 'reserve' file</td></tr>
<tr><td>h2.objectCache</td><td>true</td><td>Cache commonly used objects (integers, strings)</td></tr>
<tr><td>h2.objectCacheSize</td><td>1024</td><td>Size of object cache</td></tr>
<tr><td>h2.objectCacheMaxPerElementSize</td><td>4096</td><td>Maximum size of an object in the cache</td></tr>
<tr><td>h2.clientTraceDirectory</td><td>trace.db/</td><td>Directory where the trace files of the JDBC client are stored (only for client / server)</td></tr>
<tr><td>h2.scriptDirectory</td><td></td><td>Relative or absolute directory where the script files are stored to or read from</td></tr>
</table> </table>
<br /><a name="glossary_links"></a> <br /><a name="glossary_links"></a>
......
...@@ -12,33 +12,104 @@ Frequently Asked Questions ...@@ -12,33 +12,104 @@ Frequently Asked Questions
<h1>Frequently Asked Questions</h1> <h1>Frequently Asked Questions</h1>
<a href="#known_bugs">
Are there any known bugs? When is the next release?</a><br />
<a href="#open_source">
Is this Database Engine Open Source?</a><br />
<a href="#query_slow">
My query is slow</a><br />
<a href="#create_database">
How to Create a New Database?</a><br />
<a href="#connect">
How to Connect to a Database?</a><br />
<a href="#database_files">
Where are the Database Files Stored?</a><br />
<a href="#size_limit">
What is the Size Limit (maximum size) of a Database?</a><br />
<a href="#reliable">
Is it Reliable?</a><br />
<a href="#gcj">
Is the GCJ version stable? Faster?</a><br />
<br /><a name="known_bugs"></a>
<h3>Are there any known bugs? When is the next release?</h3> <h3>Are there any known bugs? When is the next release?</h3>
<p>
Usually, bugs get fixes as they are found. There is a release every few weeks. Usually, bugs get fixes as they are found. There is a release every few weeks.
Here is the list of known and confirmed issues as of Here is the list of known and confirmed issues as of
2007-04-29: 2007-04-29:
</p>
<ul> <ul>
<li>Can not build using the test cases ant with JDK 1.3 at the moment. However most things are fixed. <li>Can not build using the test cases ant with JDK 1.3 at the moment. However most things are fixed.
</li><li>Some problems have been found with right outer join. Internally, it is converted to left outer join, which </li><li>Some problems have been found with right outer join. Internally, it is converted to left outer join, which
does not always produce the correct results when used in combination with other joins. does not always produce the correct results when used in combination with other joins.
</li></ul> </li></ul>
<br /><a name="open_source"></a>
<h3>Is this Database Engine Open Source?</h3> <h3>Is this Database Engine Open Source?</h3>
<p>
Yes. It is free to use and distribute, and the source code is included. Yes. It is free to use and distribute, and the source code is included.
See also under license. See also under license.
</p>
<h3>Is the GCJ version stable? Faster?</h3> <br /><a name="query_slow"></a>
The GCJ version is not as stable as the Java version. <h3>My query is slow</h3>
When running the regression test with the GCJ version, sometimes the application just stops <p>
at what seems to be a random point without error message. Slow SELECT (or DELETE, UPDATE, MERGE) statement can have multiple reasons.
Currently, the GCJ version is also slower than when using the Sun VM. Follow this checklist:
However, the startup of the GCJ version is faster than when using a VM. </p>
<ul>
<li>Run ANALYSE (see documentation for details).
</li><li>Run the query with EXPLAIN and check if indexes are used (see documentation for details).
</li><li>If required, create additional indexes and try again using ANALZYE and EXPLAIN.
</li><li>If it doesn't help please report the problem.
</li>
</ul>
<br /><a name="create_database"></a>
<h3>How to Create a New Database?</h3>
<p>
By default, a new database is automatically created if it does not yet exist.
</p>
<br /><a name="connect"></a>
<h3>How to Connect to a Database?</h3>
<p>
The database driver is <code>org.h2.Driver</code>,
and the database URL starts with <code>jdbc:h2:</code>.
To connect to a database using JDBC, use the following code:
</p>
<pre>
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:test", "sa", "");
</pre>
<br /><a name="database_files"></a>
<h3>Where are the Database Files Stored?</h3>
<p>
If the base directory is not set, the database files are stored in the directory where the application is started
(the current working directory). When using the H2 Console application from the start menu, this is [Installation Directory]/bin.
The base directory can be set in the database URL. A fixed or relative path can be used. When using the URL
jdbc:h2:file:data/sample, the database is stored in the directory data (relative to the current working directory).
The directory must exist. It is also possible to use the fully qualified directory (and for Windows, drive) name.
Example: jdbc:h2:file:C:/data/test
</p>
<br /><a name="size_limit"></a>
<h3>What is the Size Limit (maximum size) of a Database?</h3>
<p>
The theoretical limit is currently 256 GB for the data. This number is excluding BLOB and CLOB data:
Every CLOB or BLOB can be up to 256 GB as well. The size limit of the index data is 256 GB as well.
</p>
<br /><a name="reliable"></a>
<h3>Is it Reliable?</h3> <h3>Is it Reliable?</h3>
<p>
That is not easy to say. It is still a quite new product. A lot of tests have been written, That is not easy to say. It is still a quite new product. A lot of tests have been written,
and the code coverage of these tests is very high. Randomized stress tests and the code coverage of these tests is very high. Randomized stress tests
are run regularly. But as this is a relatively new product, there are probably are run regularly. But as this is a relatively new product, there are probably
some problems that have not yet been found. some problems that have not yet been found.
Areas that are not completely tested: Areas that are not completely tested:
</p>
<ul> <ul>
<li>Platforms other than Windows XP and the Sun JVM 1.4 <li>Platforms other than Windows XP and the Sun JVM 1.4
</li><li>Data types BLOB, CLOB, VARCHAR_IGNORECASE, OTHER </li><li>Data types BLOB, CLOB, VARCHAR_IGNORECASE, OTHER
...@@ -54,7 +125,9 @@ Areas that are not completely tested: ...@@ -54,7 +125,9 @@ Areas that are not completely tested:
</li><li>Wide indexes with large VARCHAR or VARBINARY columns and / or with a lot of columns </li><li>Wide indexes with large VARCHAR or VARBINARY columns and / or with a lot of columns
</li></ul> </li></ul>
<p>
Areas considered Experimental: Areas considered Experimental:
</p>
<ul> <ul>
<li>ODBC driver and the GCJ native version on Windows <li>ODBC driver and the GCJ native version on Windows
</li><li>Linear Hash Index </li><li>Linear Hash Index
...@@ -62,28 +135,14 @@ Areas considered Experimental: ...@@ -62,28 +135,14 @@ Areas considered Experimental:
</li><li>The ARRAY data type and related functionality. </li><li>The ARRAY data type and related functionality.
</li></ul> </li></ul>
<h3>How to Create a New Database?</h3> <br /><a name="gcj"></a>
By default, a new database is automatically created if it does not yet exist. <h3>Is the GCJ version stable? Faster?</h3>
<p>
<h3>How to Connect to a Database?</h3> The GCJ version is not as stable as the Java version.
The database driver is <code>org.h2.Driver</code>, When running the regression test with the GCJ version, sometimes the application just stops
and the database URL starts with <code>jdbc:h2:</code>. at what seems to be a random point without error message.
To connect to a database using JDBC, use the following code: Currently, the GCJ version is also slower than when using the Sun VM.
<pre> However, the startup of the GCJ version is faster than when using a VM.
Class.forName("org.h2.Driver"); </p>
Connection conn = DriverManager.getConnection("jdbc:h2:test", "sa", "");
</pre>
<h3>Where are the Database Files Stored?</h3>
If the base directory is not set, the database files are stored in the directory where the application is started
(the current working directory). When using the H2 Console application from the start menu, this is [Installation Directory]/bin.
The base directory can be set in the database URL. A fixed or relative path can be used. When using the URL
jdbc:h2:file:data/sample, the database is stored in the directory data (relative to the current working directory).
The directory must exist. It is also possible to use the fully qualified directory (and for Windows, drive) name.
Example: jdbc:h2:file:C:/data/test
<h3>What is the Size Limit of a Database?</h3>
The theoretical limit is currently 256 GB for the data. This number is excluding BLOB and CLOB data:
Every CLOB or BLOB can be up to 256 GB as well. The size limit of the index data is 256 GB as well.
</div></td></tr></table></body></html> </div></td></tr></table></body></html>
\ No newline at end of file
...@@ -232,6 +232,9 @@ It looks like the development of this database has stopped. The last release was ...@@ -232,6 +232,9 @@ It looks like the development of this database has stopped. The last release was
</tr><tr> </tr><tr>
<td><a href="http://incubator.apache.org/openjpa">Apache OpenJPA</a></td> <td><a href="http://incubator.apache.org/openjpa">Apache OpenJPA</a></td>
<td>Open source implementation of the Java Persistence API (JPA).</td> <td>Open source implementation of the Java Persistence API (JPA).</td>
</tr><tr>
<td><a href="http://appfuse.org">AppFuse</a></td>
<td>Helps building web applications.</td>
</tr><tr> </tr><tr>
<td><a href="http://bmarks-portlet.sourceforge.net">Bookmarks Portlet</a></td> <td><a href="http://bmarks-portlet.sourceforge.net">Bookmarks Portlet</a></td>
<td>JSR168 compliant bookmarks management portlet application.</td> <td>JSR168 compliant bookmarks management portlet application.</td>
...@@ -253,6 +256,9 @@ It looks like the development of this database has stopped. The last release was ...@@ -253,6 +256,9 @@ It looks like the development of this database has stopped. The last release was
</tr><tr> </tr><tr>
<td><a href="http://jamwiki.org">JAMWiki</a></td> <td><a href="http://jamwiki.org">JAMWiki</a></td>
<td>Java-based Wiki engine.</td> <td>Java-based Wiki engine.</td>
</tr><tr>
<td><a href="http://mywebpage.netscape.com/davidlbarron/javaplayer.html">JavaPlayer</a></td>
<td>Pure Java MP3 player</td>
</tr><tr> </tr><tr>
<td><a href="http://www.jpox.org">JPOX</a></td> <td><a href="http://www.jpox.org">JPOX</a></td>
<td>Java persistent objects</td> <td>Java persistent objects</td>
......
...@@ -37,7 +37,24 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -37,7 +37,24 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3> <h3>Version 1.0 (Current)</h3>
<h3>Version 1.0 / 2007-TODO</h3><ul> <h3>Version 1.0 / 2007-TODO</h3><ul>
<li>In INSERT and MERGE statements, each column may only be specified once now. <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>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>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>After calling SHUTDOWN and closing the connection and a superfluous error message appeared in the trace file. Fixed.
...@@ -1312,7 +1329,6 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1312,7 +1329,6 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>Clustering: recovery needs to becomes fully automatic. </li><li>Clustering: recovery needs to becomes fully automatic.
</li><li>Date: default date is '1970-01-01' (is it 1900-01-01 in the standard / other databases?) </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>Test and document UPDATE TEST SET (ID, NAME) = (SELECT ID*10, NAME || '!' FROM TEST T WHERE T.ID=TEST.ID);
</li><li>Support home directory as ~ in database URL (jdbc:h2:file:~/.dir/db)
</li><li>Better space re-use in the files after deleting data (shrink the files) </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>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>Index summary is only written if log=2; maybe write it also when log=1 and everything is fine (and no in doubt transactions)
......
...@@ -2814,7 +2814,7 @@ public class Parser { ...@@ -2814,7 +2814,7 @@ public class Parser {
scale = scale == -1 ? dataType.defaultScale : scale; scale = scale == -1 ? dataType.defaultScale : scale;
if(dataType.supportsPrecision || dataType.supportsScale) { if(dataType.supportsPrecision || dataType.supportsScale) {
if(readIf("(")) { if(readIf("(")) {
precision = getPositiveInt(); precision = readLong();
if(readIf("K")) { if(readIf("K")) {
precision *= 1024; precision *= 1024;
} else if(readIf("M")) { } else if(readIf("M")) {
...@@ -2822,8 +2822,8 @@ public class Parser { ...@@ -2822,8 +2822,8 @@ public class Parser {
} else if(readIf("G")) { } else if(readIf("G")) {
precision *= 1024 * 1024 * 1024; precision *= 1024 * 1024 * 1024;
} }
if(precision > Integer.MAX_VALUE) { if(precision > Long.MAX_VALUE) {
precision = Integer.MAX_VALUE; precision = Long.MAX_VALUE;
} }
original += "(" + precision; original += "(" + precision;
// oracle syntax // oracle syntax
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
*/ */
package org.h2.command.dml; package org.h2.command.dml;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
...@@ -52,7 +52,7 @@ public class BackupCommand extends Prepared { ...@@ -52,7 +52,7 @@ public class BackupCommand extends Prepared {
try { try {
String name = db.getName(); String name = db.getName();
name = FileUtils.getFileName(name); name = FileUtils.getFileName(name);
FileOutputStream zip = new FileOutputStream(fileName); OutputStream zip = FileUtils.openFileOutputStream(fileName);
ZipOutputStream out = new ZipOutputStream(zip); ZipOutputStream out = new ZipOutputStream(zip);
LogSystem log = db.getLog(); LogSystem log = db.getLog();
try { try {
...@@ -110,7 +110,7 @@ public class BackupCommand extends Prepared { ...@@ -110,7 +110,7 @@ public class BackupCommand extends Prepared {
private void backupFile(ZipOutputStream out, String fn) throws SQLException, IOException { private void backupFile(ZipOutputStream out, String fn) throws SQLException, IOException {
out.putNextEntry(new ZipEntry(FileUtils.getFileName(fn))); out.putNextEntry(new ZipEntry(FileUtils.getFileName(fn)));
FileInputStream in = new FileInputStream(fn); InputStream in = FileUtils.openFileInputStream(fn);
IOUtils.copyAndCloseInput(in, out); IOUtils.copyAndCloseInput(in, out);
out.closeEntry(); out.closeEntry();
} }
......
...@@ -6,9 +6,6 @@ package org.h2.command.dml; ...@@ -6,9 +6,6 @@ package org.h2.command.dml;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
...@@ -34,8 +31,8 @@ public class ScriptBase extends Prepared implements DataHandler { ...@@ -34,8 +31,8 @@ public class ScriptBase extends Prepared implements DataHandler {
private String cipher; private String cipher;
private byte[] key; private byte[] key;
private FileStore store; private FileStore store;
private FileOutputStream outStream; private OutputStream outStream;
private FileInputStream inStream; private InputStream inStream;
protected OutputStream out; protected OutputStream out;
protected InputStream in; protected InputStream in;
protected String fileName; protected String fileName;
...@@ -95,7 +92,7 @@ public class ScriptBase extends Prepared implements DataHandler { ...@@ -95,7 +92,7 @@ public class ScriptBase extends Prepared implements DataHandler {
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS); out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else { } else {
try { try {
outStream = FileUtils.openFileOutputStream(new File(fileName)); outStream = FileUtils.openFileOutputStream(fileName);
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, fileName); throw Message.convertIOException(e, fileName);
} }
...@@ -110,10 +107,10 @@ public class ScriptBase extends Prepared implements DataHandler { ...@@ -110,10 +107,10 @@ public class ScriptBase extends Prepared implements DataHandler {
} }
if(isEncrypted()) { if(isEncrypted()) {
initStore(); initStore();
in = new FileStoreInputStream(store, this, compressionAlgorithm != null); in = new FileStoreInputStream(store, this, compressionAlgorithm != null, false);
} else { } else {
try { try {
inStream = new FileInputStream(fileName); inStream = FileUtils.openFileInputStream(fileName);
} catch (IOException e) { } catch (IOException e) {
throw Message.convertIOException(e, fileName); throw Message.convertIOException(e, fileName);
} }
......
...@@ -4,13 +4,11 @@ ...@@ -4,13 +4,11 @@
*/ */
package org.h2.command.dml; package org.h2.command.dml;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader; import java.io.Reader;
import java.io.Writer;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
...@@ -357,28 +355,28 @@ public class ScriptCommand extends ScriptBase { ...@@ -357,28 +355,28 @@ public class ScriptCommand extends ScriptBase {
} }
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT BDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART"); ResultSet rs = stat.executeQuery("SELECT BDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART");
FileOutputStream out = new FileOutputStream(TEMP_LOB_FILENAME); OutputStream out = FileUtils.openFileOutputStream(TEMP_LOB_FILENAME);
while(rs.next()) { while(rs.next()) {
InputStream in = rs.getBinaryStream(1); InputStream in = rs.getBinaryStream(1);
IOUtils.copyAndCloseInput(in, out); IOUtils.copyAndCloseInput(in, out);
} }
out.close(); out.close();
stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id); stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id);
return new FileInputStream(TEMP_LOB_FILENAME); return FileUtils.openFileInputStream(TEMP_LOB_FILENAME);
} }
// called from the script // called from the script
public static Reader combineClob(Connection conn, int id) throws SQLException, IOException { public static Reader combineClob(Connection conn, int id) throws SQLException, IOException {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT CDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART"); ResultSet rs = stat.executeQuery("SELECT CDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART");
FileWriter out = new FileWriter(TEMP_LOB_FILENAME); Writer out = FileUtils.openFileWriter(TEMP_LOB_FILENAME, false);
while(rs.next()) { while(rs.next()) {
Reader in = rs.getCharacterStream(1); Reader in = rs.getCharacterStream(1);
IOUtils.copyAndCloseInput(in, out); IOUtils.copyAndCloseInput(in, out);
} }
out.close(); out.close();
stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id); stat.execute("DELETE FROM SYSTEM_LOB_STREAM WHERE ID=" + id);
return new FileReader(TEMP_LOB_FILENAME); return FileUtils.openFileReader(TEMP_LOB_FILENAME);
} }
private void reset() throws SQLException { private void reset() throws SQLException {
......
...@@ -67,8 +67,8 @@ package org.h2.engine; ...@@ -67,8 +67,8 @@ package org.h2.engine;
*/ */
public class Constants { public class Constants {
public static final int BUILD_ID = 47; public static final int BUILD_ID = 48;
private static final String BUILD = "2007-06-13"; private static final String BUILD = "2007-06-14";
public static final int VERSION_MAJOR = 1; public static final int VERSION_MAJOR = 1;
public static final int VERSION_MINOR = 0; public static final int VERSION_MINOR = 0;
...@@ -245,6 +245,8 @@ public class Constants { ...@@ -245,6 +245,8 @@ public class Constants {
public static final int OBJECT_CACHE_MAX_PER_ELEMENT_SIZE = getIntSetting("h2.objectCacheMaxPerElementSize", 4096); public static final int OBJECT_CACHE_MAX_PER_ELEMENT_SIZE = getIntSetting("h2.objectCacheMaxPerElementSize", 4096);
public static final String CLIENT_TRACE_DIRECTORY = getStringSetting("h2.clientTraceDirectory", "trace.db/"); public static final String CLIENT_TRACE_DIRECTORY = getStringSetting("h2.clientTraceDirectory", "trace.db/");
public static int MAX_FILE_RETRY = Math.max(1, getIntSetting("h2.maxFileRetry", 16)); public static int MAX_FILE_RETRY = Math.max(1, getIntSetting("h2.maxFileRetry", 16));
public static boolean INDEX_NEW = getBooleanSetting("h2.indexNew", false);
public static boolean LOB_CLOSE_BETWEEN_READS = getBooleanSetting("h2.lobCloseBetweenReads", false);
public static boolean getBooleanSetting(String name, boolean defaultValue) { public static boolean getBooleanSetting(String name, boolean defaultValue) {
String s = System.getProperty(name); String s = System.getProperty(name);
......
...@@ -4,9 +4,8 @@ ...@@ -4,9 +4,8 @@
*/ */
package org.h2.engine; package org.h2.engine;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
...@@ -161,7 +160,7 @@ public class Database implements DataHandler { ...@@ -161,7 +160,7 @@ public class Database implements DataHandler {
MemoryFile file = FileUtils.getMemoryFile(fileName); MemoryFile file = FileUtils.getMemoryFile(fileName);
magic = file.getMagic(); magic = file.getMagic();
} else { } else {
FileInputStream fin = new FileInputStream(fileName); InputStream fin = FileUtils.openFileInputStream(fileName);
magic = IOUtils.readBytesAndClose(fin, magicBinary.length); magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
} }
if(ByteUtils.compareNotNull(magic, magicText) == 0) { if(ByteUtils.compareNotNull(magic, magicText) == 0) {
...@@ -1372,8 +1371,7 @@ public class Database implements DataHandler { ...@@ -1372,8 +1371,7 @@ public class Database implements DataHandler {
public String getDatabasePath() { public String getDatabasePath() {
if(persistent) { if(persistent) {
File parent = new File(databaseName).getAbsoluteFile(); return FileUtils.getAbsolutePath(databaseName);
return parent.getAbsolutePath();
} else { } else {
return null; return null;
} }
......
...@@ -286,8 +286,7 @@ public class SessionRemote implements SessionInterface, DataHandler { ...@@ -286,8 +286,7 @@ public class SessionRemote implements SessionInterface, DataHandler {
String message = transfer.readString(); String message = transfer.readString();
int errorCode = transfer.readInt(); int errorCode = transfer.readInt();
String trace = transfer.readString(); String trace = transfer.readString();
message = message + "\n" + trace; throw new JdbcSQLException(message, sqlstate, errorCode, null, trace);
throw new JdbcSQLException(message, sqlstate, errorCode, null);
} else if(status == STATUS_CLOSED) { } else if(status == STATUS_CLOSED) {
transferList = null; transferList = null;
} }
......
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.index;
import java.sql.SQLException;
import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.expression.Comparison;
import org.h2.expression.Parameter;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.table.Column;
import org.h2.table.TableView;
import org.h2.util.IntArray;
import org.h2.util.SmallLRUCache;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
public class ViewIndexNew extends Index {
private String querySQL;
private ObjectArray originalParameters;
private SmallLRUCache costCache = new SmallLRUCache(Constants.VIEW_INDEX_CACHE_SIZE);
private boolean recursive;
private int[] masks;
private String planSQL;
private Query query;
public ViewIndexNew(TableView view, String querySQL, ObjectArray originalParameters, boolean recursive) {
super(view, 0, null, null, IndexType.createNonUnique(false));
this.querySQL = querySQL;
this.originalParameters = originalParameters;
this.recursive = recursive;
columns = new Column[0];
}
public ViewIndexNew(TableView view, ViewIndexNew index, Session session, int[] masks) throws SQLException {
super(view, 0, null, null, IndexType.createNonUnique(false));
this.querySQL = index.querySQL;
this.originalParameters = index.originalParameters;
this.recursive = index.recursive;
this.masks = masks;
columns = new Column[0];
query = getQuery(session, masks);
planSQL = query.getPlanSQL();
}
public String getPlanSQL() {
return planSQL;
}
public void close(Session session) throws SQLException {
}
public void add(Session session, Row row) throws SQLException {
throw Message.getUnsupportedException();
}
public void remove(Session session, Row row) throws SQLException {
throw Message.getUnsupportedException();
}
private static class CostElement {
long evaluatedAt;
double cost;
}
public double getCost(Session session, int[] masks) throws SQLException {
IntArray masksArray = new IntArray(masks == null ? new int[0] : masks);
CostElement cachedCost = (CostElement) costCache.get(masksArray);
if(cachedCost != null) {
long time = System.currentTimeMillis();
if(time < cachedCost.evaluatedAt + Constants.VIEW_COST_CACHE_MAX_AGE) {
return cachedCost.cost;
}
}
Query query = (Query)session.prepare(querySQL, true);
if(masks == null) {
columns = new Column[0];
} else {
IntArray paramIndex = new IntArray();
for(int i=0; i<masks.length; i++) {
int mask = masks[i];
if(mask == 0) {
continue;
}
paramIndex.add(i);
}
int len = paramIndex.size();
columns = new Column[len];
for(int i=0; i<len; i++) {
int idx = paramIndex.get(i);
Column col = table.getColumn(idx);
columns[i] = col;
int mask = masks[idx];
if((mask & IndexCondition.EQUALITY) != 0) {
Parameter param = new Parameter(0);
query.addGlobalCondition(param, idx, Comparison.EQUAL);
} else {
if((mask & IndexCondition.START) != 0) {
Parameter param = new Parameter(0);
query.addGlobalCondition(param, idx, Comparison.BIGGER_EQUAL);
}
if((mask & IndexCondition.END) != 0) {
Parameter param = new Parameter(0);
query.addGlobalCondition(param, idx, Comparison.SMALLER_EQUAL);
}
}
}
if(recursive) {
return 10;
}
String sql = query.getPlanSQL();
query = (Query)session.prepare(sql);
}
double cost = query.getCost();
cachedCost = new CostElement();
cachedCost.evaluatedAt = System.currentTimeMillis();
cachedCost.cost = cost;
costCache.put(masksArray, cachedCost);
return cost;
}
public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException {
ObjectArray paramList = query.getParameters();
int idx = 0;
for(int i=0; originalParameters != null && i<originalParameters.size(); i++) {
Parameter orig = (Parameter) originalParameters.get(i);
Value value = orig.getValue(session);
Parameter param = (Parameter) paramList.get(idx++);
param.setValue(value);
}
for(int i=0; first != null && i<first.getColumnCount(); i++) {
if(first != null) {
Value v = first.getValue(i);
if(v != null) {
Parameter param = (Parameter) paramList.get(idx++);
param.setValue(v);
}
}
// for equality, only one parameter is used (first == last)
if(masks[i] != IndexCondition.EQUALITY && last != null) {
Value v = last.getValue(i);
if(v != null) {
Parameter param = (Parameter) paramList.get(idx++);
param.setValue(v);
}
}
}
LocalResult result = query.query(0);
return new ViewCursor(table, result);
}
private Query getQuery(Session session, int[] masks) throws SQLException {
Query query = (Query)session.prepare(querySQL, true);
if(masks == null) {
return query;
}
int firstIndexParam = query.getParameters().size();
IntArray paramIndex = new IntArray();
for(int i=0; i<masks.length; i++) {
int mask = masks[i];
if(mask == 0) {
continue;
}
paramIndex.add(i);
if((mask & IndexCondition.RANGE) == IndexCondition.RANGE) {
// two parameters for range queries: >= x AND <= y
paramIndex.add(i);
}
}
int len = paramIndex.size();
columns = new Column[len];
for(int i=0; i<len;) {
int idx = paramIndex.get(i);
Column col = table.getColumn(idx);
columns[i] = col;
int mask = masks[idx];
if((mask & IndexCondition.EQUALITY) == IndexCondition.EQUALITY) {
Parameter param = new Parameter(firstIndexParam + i);
query.addGlobalCondition(param, idx, Comparison.EQUAL);
i++;
} else {
if((mask & IndexCondition.START) == IndexCondition.START) {
Parameter param = new Parameter(firstIndexParam + i);
query.addGlobalCondition(param, idx, Comparison.BIGGER_EQUAL);
i++;
}
if((mask & IndexCondition.END) == IndexCondition.END) {
Parameter param = new Parameter(firstIndexParam + i);
query.addGlobalCondition(param, idx, Comparison.SMALLER_EQUAL);
i++;
}
}
}
String sql = query.getPlanSQL();
query = (Query)session.prepare(sql, true);
return query;
}
public long getCost(int[] masks) throws SQLException {
if(masks != null) {
throw Message.getUnsupportedException();
}
return Long.MAX_VALUE;
}
public void remove(Session session) throws SQLException {
throw Message.getUnsupportedException();
}
public void truncate(Session session) throws SQLException {
throw Message.getUnsupportedException();
}
public void checkRename() throws SQLException {
throw Message.getUnsupportedException();
}
public boolean needRebuild() {
return false;
}
public boolean canGetFirstOrLast(boolean first) {
return false;
}
public Value findFirstOrLast(Session session, boolean first) throws SQLException {
throw Message.getUnsupportedException();
}
public void setRecursive(boolean value) {
this.recursive = value;
}
}
...@@ -18,6 +18,7 @@ public class JdbcSQLException extends SQLException { ...@@ -18,6 +18,7 @@ public class JdbcSQLException extends SQLException {
private static final long serialVersionUID = -8200821788226954151L; private static final long serialVersionUID = -8200821788226954151L;
private Throwable cause; private Throwable cause;
private String originalMessage; private String originalMessage;
private String trace;
/** /**
* Creates a SQLException a message, sqlstate and cause. * Creates a SQLException a message, sqlstate and cause.
...@@ -26,10 +27,11 @@ public class JdbcSQLException extends SQLException { ...@@ -26,10 +27,11 @@ public class JdbcSQLException extends SQLException {
* @param state the SQL state * @param state the SQL state
* @param cause the exception that was the reason for this exception * @param cause the exception that was the reason for this exception
*/ */
public JdbcSQLException(String message, String state, int errorCode, Throwable cause) { public JdbcSQLException(String message, String state, int errorCode, Throwable cause, String trace) {
super(message + " [" + state + "-" + Constants.BUILD_ID + "]", state, errorCode); super(message + " [" + state + "-" + Constants.BUILD_ID + "]", state, errorCode);
this.originalMessage = message; this.originalMessage = message;
this.cause = cause; this.cause = cause;
this.trace = trace;
//#ifdef JDK14 //#ifdef JDK14
initCause(cause); initCause(cause);
//#endif //#endif
...@@ -107,5 +109,13 @@ public class JdbcSQLException extends SQLException { ...@@ -107,5 +109,13 @@ public class JdbcSQLException extends SQLException {
public Throwable getOriginalCause() { public Throwable getOriginalCause() {
return cause; return cause;
} }
public String toString() {
if(trace == null) {
return super.toString();
} else {
return trace;
}
}
} }
...@@ -62,7 +62,7 @@ public class Message { ...@@ -62,7 +62,7 @@ public class Message {
public static JdbcSQLException getSQLException(int errorCode, String[] param, Throwable cause) { public static JdbcSQLException getSQLException(int errorCode, String[] param, Throwable cause) {
String sqlstate = getState(errorCode); String sqlstate = getState(errorCode);
String message = translate(sqlstate, param); String message = translate(sqlstate, param);
return new JdbcSQLException(message, sqlstate, errorCode, cause); return new JdbcSQLException(message, sqlstate, errorCode, cause, null);
} }
public static SQLException getSyntaxError(String sql, int index) { public static SQLException getSyntaxError(String sql, int index) {
...@@ -345,9 +345,13 @@ public class Message { ...@@ -345,9 +345,13 @@ public class Message {
} }
if(e instanceof JdbcSQLException) { if(e instanceof JdbcSQLException) {
JdbcSQLException j = (JdbcSQLException) e; JdbcSQLException j = (JdbcSQLException) e;
return new JdbcSQLException(j.getOriginalMessage()+"; SQL statement: "+sql, j.getSQLState(), j.getErrorCode(), j); return new JdbcSQLException(j.getOriginalMessage()+"; SQL statement: "+sql,
j.getSQLState(),
j.getErrorCode(), j, null);
} else { } else {
return new JdbcSQLException(e.getMessage()+"; SQL statement: "+sql, e.getSQLState(), e.getErrorCode(), e); return new JdbcSQLException(e.getMessage()+"; SQL statement: "+sql,
e.getSQLState(),
e.getErrorCode(), e, null);
} }
} }
......
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
*/ */
package org.h2.message; package org.h2.message;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.util.FileUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
public class TraceObject { public class TraceObject {
...@@ -183,7 +184,7 @@ public class TraceObject { ...@@ -183,7 +184,7 @@ public class TraceObject {
synchronized(this.getClass()) { synchronized(this.getClass()) {
// e.printStackTrace(); // e.printStackTrace();
try { try {
FileWriter writer = new FileWriter(Constants.LOG_ALL_ERRORS_FILE, true); Writer writer = FileUtils.openFileWriter(Constants.LOG_ALL_ERRORS_FILE, true);
PrintWriter p = new PrintWriter(writer); PrintWriter p = new PrintWriter(writer);
e.printStackTrace(p); e.printStackTrace(p);
p.close(); p.close();
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
*/ */
package org.h2.message; package org.h2.message;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Writer;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
...@@ -40,7 +40,7 @@ public class TraceSystem { ...@@ -40,7 +40,7 @@ public class TraceSystem {
private long lastCheck; private long lastCheck;
private SmallLRUCache traces; private SmallLRUCache traces;
private SimpleDateFormat dateFormat; private SimpleDateFormat dateFormat;
private FileWriter fileWriter; private Writer fileWriter;
private PrintWriter printWriter; private PrintWriter printWriter;
private static final int CHECK_SIZE_EACH_WRITES = 128; private static final int CHECK_SIZE_EACH_WRITES = 128;
private int checkSize; private int checkSize;
......
...@@ -13,9 +13,8 @@ import java.sql.SQLException; ...@@ -13,9 +13,8 @@ import java.sql.SQLException;
//#ifdef JDK14 //#ifdef JDK14
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.InputStream;
import java.io.FileInputStream; import java.io.OutputStream;
import java.io.FileOutputStream;
import java.security.Key; import java.security.Key;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.KeyStore; import java.security.KeyStore;
...@@ -189,23 +188,24 @@ public class SecureSocketFactory { ...@@ -189,23 +188,24 @@ public class SecureSocketFactory {
private void setKeystore() throws IOException, SQLException { private void setKeystore() throws IOException, SQLException {
Properties p = System.getProperties(); Properties p = System.getProperties();
if (p.getProperty(KEYSTORE_KEY) == null) { if (p.getProperty(KEYSTORE_KEY) == null) {
File file = FileUtils.getFileInUserHome(KEYSTORE); String fileName = FileUtils.getFileInUserHome(KEYSTORE);
byte[] data = getKeyStoreBytes(getKeyStore(KEYSTORE_PASSWORD), KEYSTORE_PASSWORD); byte[] data = getKeyStoreBytes(getKeyStore(KEYSTORE_PASSWORD), KEYSTORE_PASSWORD);
boolean needWrite = true; boolean needWrite = true;
if (file.exists() && file.length() == data.length) { if (FileUtils.exists(fileName) && FileUtils.length(fileName) == data.length) {
// don't need to overwrite the file if it did not change // don't need to overwrite the file if it did not change
FileInputStream fin = new FileInputStream(file); InputStream fin = FileUtils.openFileInputStream(fileName);
byte[] now = IOUtils.readBytesAndClose(fin, 0); byte[] now = IOUtils.readBytesAndClose(fin, 0);
if (now != null && ByteUtils.compareNotNull(data, now) == 0) { if (now != null && ByteUtils.compareNotNull(data, now) == 0) {
needWrite = false; needWrite = false;
} }
} }
if (needWrite) { if (needWrite) {
FileOutputStream out = new FileOutputStream(file); OutputStream out = FileUtils.openFileOutputStream(fileName);
out.write(data); out.write(data);
out.close(); out.close();
} }
System.setProperty(KEYSTORE_KEY, file.getAbsolutePath()); String absolutePath = FileUtils.getAbsolutePath(fileName);
System.setProperty(KEYSTORE_KEY, absolutePath);
} }
if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) { if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) {
System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD); System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD);
......
...@@ -17,6 +17,7 @@ import org.h2.engine.Engine; ...@@ -17,6 +17,7 @@ import org.h2.engine.Engine;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.engine.SessionRemote; import org.h2.engine.SessionRemote;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.result.ResultColumn; import org.h2.result.ResultColumn;
...@@ -128,9 +129,15 @@ public class TcpServerThread implements Runnable { ...@@ -128,9 +129,15 @@ public class TcpServerThread implements Runnable {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer)); e.printStackTrace(new PrintWriter(writer));
String trace = writer.toString(); String trace = writer.toString();
String message;
if(e instanceof JdbcSQLException) {
message = ((JdbcSQLException) e).getOriginalMessage();
} else {
message = e.getMessage();
}
transfer.writeInt(SessionRemote.STATUS_ERROR). transfer.writeInt(SessionRemote.STATUS_ERROR).
writeString(s.getSQLState()). writeString(s.getSQLState()).
writeString(e.getMessage()). writeString(message).
writeInt(s.getErrorCode()). writeInt(s.getErrorCode()).
writeString(trace). writeString(trace).
flush(); flush();
......
...@@ -5,18 +5,19 @@ ...@@ -5,18 +5,19 @@
package org.h2.server.ftp; package org.h2.server.ftp;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.sql.SQLException;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
public class FileObjectNative implements FileObject { public class FileObjectNative implements FileObject {
private File file; private File file;
static FileObjectNative get(String name) { static FileObjectNative get(String name) {
name = FileUtils.translateFileName(name);
return new FileObjectNative(new File(name)); return new FileObjectNative(new File(name));
} }
...@@ -78,12 +79,16 @@ public class FileObjectNative implements FileObject { ...@@ -78,12 +79,16 @@ public class FileObjectNative implements FileObject {
} }
public void write(InputStream in) throws IOException { public void write(InputStream in) throws IOException {
FileOutputStream out = new FileOutputStream(file); try {
IOUtils.copyAndClose(in, out); OutputStream out = FileUtils.openFileOutputStream(file.getAbsolutePath());
IOUtils.copyAndClose(in, out);
} catch(SQLException e) {
throw new IOException(e.getMessage());
}
} }
public void read(long skip, OutputStream out) throws IOException { public void read(long skip, OutputStream out) throws IOException {
InputStream in = new FileInputStream(file); InputStream in = FileUtils.openFileInputStream(file.getAbsolutePath());
IOUtils.skipFully(in, skip); IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out); IOUtils.copyAndClose(in, out);
} }
......
...@@ -7,7 +7,6 @@ package org.h2.server.ftp; ...@@ -7,7 +7,6 @@ package org.h2.server.ftp;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
...@@ -24,6 +23,7 @@ import java.util.Properties; ...@@ -24,6 +23,7 @@ import java.util.Properties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.server.Service; import org.h2.server.Service;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
...@@ -155,7 +155,7 @@ public class FtpServer implements Service { ...@@ -155,7 +155,7 @@ public class FtpServer implements Service {
if("-ftpPort".equals(args[i])) { if("-ftpPort".equals(args[i])) {
port = MathUtils.decodeInt(args[++i]); port = MathUtils.decodeInt(args[++i]);
} else if("-ftpDir".equals(args[i])) { } else if("-ftpDir".equals(args[i])) {
root = args[++i]; root = FileUtils.translateFileName(args[++i]);
} else if("-ftpRead".equals(args[i])) { } else if("-ftpRead".equals(args[i])) {
readUserName = args[++i]; readUserName = args[++i];
} else if("-ftpWrite".equals(args[i])) { } else if("-ftpWrite".equals(args[i])) {
...@@ -273,8 +273,8 @@ public class FtpServer implements Service { ...@@ -273,8 +273,8 @@ public class FtpServer implements Service {
private void openOutput() { private void openOutput() {
if(outFile != null) { if(outFile != null) {
try { try {
this.out = new FileOutputStream(outFile); this.out = FileUtils.openFileOutputStream(outFile);
} catch(IOException e) { } catch(Exception e) {
// ignore // ignore
} }
outFile = null; outFile = null;
......
...@@ -4,10 +4,8 @@ ...@@ -4,10 +4,8 @@
*/ */
package org.h2.server.web; package org.h2.server.web;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection; import java.sql.Connection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -115,15 +113,15 @@ public class AppServer { ...@@ -115,15 +113,15 @@ public class AppServer {
connInfoMap.remove(name); connInfoMap.remove(name);
} }
private File getPropertiesFile() { private String getPropertiesFileName() {
// store the properties in the user directory // store the properties in the user directory
return FileUtils.getFileInUserHome(Constants.SERVER_PROPERTIES_FILE); return FileUtils.getFileInUserHome(Constants.SERVER_PROPERTIES_FILE);
} }
Properties loadProperties() { Properties loadProperties() {
File file = getPropertiesFile(); String fileName = getPropertiesFileName();
try { try {
return FileUtils.loadProperties(file); return FileUtils.loadProperties(fileName);
} catch(IOException e) { } catch(IOException e) {
// TODO log exception // TODO log exception
return new Properties(); return new Properties();
...@@ -194,10 +192,10 @@ public class AppServer { ...@@ -194,10 +192,10 @@ public class AppServer {
prop.setProperty(String.valueOf(len - i - 1), info.getString()); prop.setProperty(String.valueOf(len - i - 1), info.getString());
} }
} }
FileOutputStream out = new FileOutputStream(getPropertiesFile()); OutputStream out = FileUtils.openFileOutputStream(getPropertiesFileName());
prop.store(out, Constants.SERVER_PROPERTIES_TITLE); prop.store(out, Constants.SERVER_PROPERTIES_TITLE);
out.close(); out.close();
} catch(IOException e) { } catch(Exception e) {
TraceSystem.traceThrowable(e); TraceSystem.traceThrowable(e);
} }
} }
......
...@@ -33,6 +33,7 @@ public class FileLister { ...@@ -33,6 +33,7 @@ public class FileLister {
* @throws SQLException * @throws SQLException
*/ */
public static ArrayList getDatabaseFiles(String dir, String db, boolean all) throws SQLException { public static ArrayList getDatabaseFiles(String dir, String db, boolean all) throws SQLException {
dir = FileUtils.translateFileName(dir);
ArrayList files = new ArrayList(); ArrayList files = new ArrayList();
if(dir == null || dir.equals("")) { if(dir == null || dir.equals("")) {
dir = "."; dir = ".";
......
...@@ -4,9 +4,8 @@ ...@@ -4,9 +4,8 @@
*/ */
package org.h2.store; package org.h2.store;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.net.BindException; import java.net.BindException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.InetAddress; import java.net.InetAddress;
...@@ -107,16 +106,14 @@ public class FileLock { ...@@ -107,16 +106,14 @@ public class FileLock {
void save() throws SQLException { void save() throws SQLException {
try { try {
File file = new File(fileName); OutputStream out = FileUtils.openFileOutputStream(fileName);
// TODO file: delegate to FileUtils
FileOutputStream out = FileUtils.openFileOutputStream(file);
try { try {
properties.setProperty("method", String.valueOf(method)); properties.setProperty("method", String.valueOf(method));
properties.store(out, MAGIC); properties.store(out, MAGIC);
} finally { } finally {
out.close(); out.close();
} }
lastWrite = file.lastModified(); lastWrite = FileUtils.getLastModified(fileName);
trace.debug("save " + properties); trace.debug("save " + properties);
} catch(IOException e) { } catch(IOException e) {
throw getException(e); throw getException(e);
...@@ -125,7 +122,7 @@ public class FileLock { ...@@ -125,7 +122,7 @@ public class FileLock {
private Properties load() throws SQLException { private Properties load() throws SQLException {
try { try {
Properties p2 = FileUtils.loadProperties(new File(fileName)); Properties p2 = FileUtils.loadProperties(fileName);
trace.debug("load " + p2); trace.debug("load " + p2);
return p2; return p2;
} catch(IOException e) { } catch(IOException e) {
...@@ -134,9 +131,8 @@ public class FileLock { ...@@ -134,9 +131,8 @@ public class FileLock {
} }
private void waitUntilOld() throws SQLException { private void waitUntilOld() throws SQLException {
File file = new File(fileName);
for(int i=0; i<10; i++) { for(int i=0; i<10; i++) {
long last = file.lastModified(); long last = FileUtils.getLastModified(fileName);
long dist = System.currentTimeMillis() - last; long dist = System.currentTimeMillis() - last;
if(dist < -TIME_GRANULARITY) { if(dist < -TIME_GRANULARITY) {
throw error("Lock file modified in the future: dist=" + dist); throw error("Lock file modified in the future: dist=" + dist);
...@@ -185,11 +181,10 @@ public class FileLock { ...@@ -185,11 +181,10 @@ public class FileLock {
Thread watchdog = new Thread(new Runnable() { Thread watchdog = new Thread(new Runnable() {
public void run() { public void run() {
try { try {
File file = new File(fileName);
while (fileName != null) { while (fileName != null) {
// trace.debug("watchdog check"); // trace.debug("watchdog check");
try { try {
if (!file.exists() || file.lastModified() != lastWrite) { if (!FileUtils.exists(fileName) || FileUtils.getLastModified(fileName) != lastWrite) {
save(); save();
} }
Thread.sleep(sleep); Thread.sleep(sleep);
...@@ -220,8 +215,7 @@ public class FileLock { ...@@ -220,8 +215,7 @@ public class FileLock {
} }
if (!FileUtils.createNewFile(fileName)) { if (!FileUtils.createNewFile(fileName)) {
waitUntilOld(); waitUntilOld();
File file = new File(fileName); long read = FileUtils.getLastModified(fileName);
long read = file.lastModified();
Properties p2 = load(); Properties p2 = load();
String m2 = p2.getProperty("method", SOCKET); String m2 = p2.getProperty("method", SOCKET);
if (m2.equals(FILE)) { if (m2.equals(FILE)) {
...@@ -255,7 +249,7 @@ public class FileLock { ...@@ -255,7 +249,7 @@ public class FileLock {
throw error("IOException"); throw error("IOException");
} }
} }
if (read != file.lastModified()) { if (read != FileUtils.getLastModified(fileName)) {
throw error("Concurrent update"); throw error("Concurrent update");
} }
FileUtils.delete(fileName); FileUtils.delete(fileName);
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
*/ */
package org.h2.store; package org.h2.store;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.lang.ref.Reference; import java.lang.ref.Reference;
...@@ -31,6 +30,7 @@ public class FileStore { ...@@ -31,6 +30,7 @@ public class FileStore {
private Reference autoDeleteReference; private Reference autoDeleteReference;
private boolean checkedWriting = true; private boolean checkedWriting = true;
private boolean synchronousMode; private boolean synchronousMode;
private String mode;
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic) throws SQLException { public static FileStore open(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
return open(handler, name, mode, magic, null, null, 0); return open(handler, name, mode, magic, null, null, 0);
...@@ -56,16 +56,17 @@ public class FileStore { ...@@ -56,16 +56,17 @@ public class FileStore {
this.handler = handler; this.handler = handler;
this.name = name; this.name = name;
this.magic = magic; this.magic = magic;
this.mode = mode;
try { try {
FileUtils.createDirs(name); FileUtils.createDirs(name);
File f = new File(name); // File f = new File(name);
if(f.exists() && !f.canWrite()) { if(FileUtils.exists(name) && !FileUtils.canWrite(name)) {
file = FileUtils.openRandomAccessFile(name, "r"); mode = "r";
} else { this.mode = mode;
file = FileUtils.openRandomAccessFile(name, mode); }
if(mode.length() > 2) { file = FileUtils.openRandomAccessFile(name, mode);
synchronousMode = true; if(mode.length() > 2) {
} synchronousMode = true;
} }
fileLength = file.length(); fileLength = file.length();
} catch(IOException e) { } catch(IOException e) {
...@@ -325,5 +326,17 @@ public class FileStore { ...@@ -325,5 +326,17 @@ public class FileStore {
public boolean isEncrypted() { public boolean isEncrypted() {
return false; return false;
} }
public void closeFile() throws IOException {
file.close();
file = null;
}
public void openFile() throws IOException {
if(file == null) {
file = FileUtils.openRandomAccessFile(name, mode);
file.seek(filePos);
}
}
} }
...@@ -16,11 +16,14 @@ public class FileStoreInputStream extends InputStream { ...@@ -16,11 +16,14 @@ public class FileStoreInputStream extends InputStream {
private FileStore store; private FileStore store;
private DataPage page; private DataPage page;
private int remaining; private int remainingInBuffer;
private CompressTool compress; private CompressTool compress;
private boolean endOfFile;
private boolean alwaysClose;
public FileStoreInputStream(FileStore store, DataHandler handler, boolean compression) throws SQLException { public FileStoreInputStream(FileStore store, DataHandler handler, boolean compression, boolean alwaysClose) throws SQLException {
this.store = store; this.store = store;
this.alwaysClose = alwaysClose;
if(compression) { if(compression) {
compress = CompressTool.getInstance(); compress = CompressTool.getInstance();
} }
...@@ -37,7 +40,7 @@ public class FileStoreInputStream extends InputStream { ...@@ -37,7 +40,7 @@ public class FileStoreInputStream extends InputStream {
} }
public int available() { public int available() {
return remaining <= 0 ? 0 : remaining; return remainingInBuffer <= 0 ? 0 : remainingInBuffer;
} }
public int read(byte[] buff) throws IOException { public int read(byte[] buff) throws IOException {
...@@ -63,21 +66,22 @@ public class FileStoreInputStream extends InputStream { ...@@ -63,21 +66,22 @@ public class FileStoreInputStream extends InputStream {
public int readBlock(byte[] buff, int off, int len) throws IOException { public int readBlock(byte[] buff, int off, int len) throws IOException {
fillBuffer(); fillBuffer();
if(store == null) { if(endOfFile) {
return -1; return -1;
} }
int l = Math.min(remaining, len); int l = Math.min(remainingInBuffer, len);
page.read(buff, off, l); page.read(buff, off, l);
remaining -= l; remainingInBuffer -= l;
return l; return l;
} }
private void fillBuffer() throws IOException { private void fillBuffer() throws IOException {
if(remaining > 0 || store==null) { if(remainingInBuffer > 0 || endOfFile) {
return; return;
} }
page.reset(); page.reset();
try { try {
store.openFile();
if(store.length() == store.getFilePointer()) { if(store.length() == store.getFilePointer()) {
close(); close();
return; return;
...@@ -87,18 +91,18 @@ public class FileStoreInputStream extends InputStream { ...@@ -87,18 +91,18 @@ public class FileStoreInputStream extends InputStream {
throw Message.convertToIOException(e); throw Message.convertToIOException(e);
} }
page.reset(); page.reset();
remaining = page.readInt(); remainingInBuffer = page.readInt();
if(remaining<0) { if(remainingInBuffer<0) {
close(); close();
return; return;
} }
page.checkCapacity(remaining); page.checkCapacity(remainingInBuffer);
// get the length to read // get the length to read
if(compress != null) { if(compress != null) {
page.checkCapacity(page.getIntLen()); page.checkCapacity(page.getIntLen());
page.readInt(); page.readInt();
} }
page.setPos(page.length() + remaining); page.setPos(page.length() + remainingInBuffer);
page.fillAligned(); page.fillAligned();
int len = page.length() - Constants.FILE_BLOCK_SIZE; int len = page.length() - Constants.FILE_BLOCK_SIZE;
page.reset(); page.reset();
...@@ -109,22 +113,26 @@ public class FileStoreInputStream extends InputStream { ...@@ -109,22 +113,26 @@ public class FileStoreInputStream extends InputStream {
page.readInt(); page.readInt();
if(compress != null) { if(compress != null) {
int uncompressed = page.readInt(); int uncompressed = page.readInt();
byte[] buff = new byte[remaining]; byte[] buff = new byte[remainingInBuffer];
page.read(buff, 0, remaining); page.read(buff, 0, remainingInBuffer);
page.reset(); page.reset();
page.checkCapacity(uncompressed); page.checkCapacity(uncompressed);
compress.expand(buff, page.getBytes(), 0); compress.expand(buff, page.getBytes(), 0);
remaining = uncompressed; remainingInBuffer = uncompressed;
} }
} catch(SQLException e) { } catch(SQLException e) {
throw Message.convertToIOException(e); throw Message.convertToIOException(e);
} }
if(alwaysClose) {
store.closeFile();
}
} }
public void close() throws IOException { public void close() throws IOException {
if(store != null) { if(store != null) {
try { try {
store.close(); store.close();
endOfFile = true;
} finally { } finally {
store = null; store = null;
} }
...@@ -134,7 +142,7 @@ public class FileStoreInputStream extends InputStream { ...@@ -134,7 +142,7 @@ public class FileStoreInputStream extends InputStream {
protected void finalize() { protected void finalize() {
if (!Constants.RUN_FINALIZE) { if (!Constants.RUN_FINALIZE) {
return; return;
} }
try { try {
close(); close();
} catch(IOException e) { } catch(IOException e) {
...@@ -144,11 +152,11 @@ public class FileStoreInputStream extends InputStream { ...@@ -144,11 +152,11 @@ public class FileStoreInputStream extends InputStream {
public int read() throws IOException { public int read() throws IOException {
fillBuffer(); fillBuffer();
if(store == null) { if(endOfFile) {
return -1; return -1;
} }
int i = page.readByte() & 0xff; int i = page.readByte() & 0xff;
remaining--; remainingInBuffer--;
return i; return i;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package org.h2.store; package org.h2.store;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
...@@ -50,5 +51,11 @@ public class MemoryFileStore extends FileStore { ...@@ -50,5 +51,11 @@ public class MemoryFileStore extends FileStore {
checkPowerOff(); checkPowerOff();
memFile.write(b, off, len); memFile.write(b, off, len);
} }
public void closeFile() throws IOException {
}
public void openFile() throws IOException {
}
} }
...@@ -277,9 +277,11 @@ public class Column { ...@@ -277,9 +277,11 @@ public class Column {
case Value.STRING: case Value.STRING:
case Value.STRING_IGNORECASE: case Value.STRING_IGNORECASE:
case Value.STRING_FIXED: case Value.STRING_FIXED:
buff.append("("); if(precision < Integer.MAX_VALUE) {
buff.append(precision); buff.append("(");
buff.append(")"); buff.append(precision);
buff.append(")");
}
break; break;
} }
} }
......
...@@ -698,6 +698,7 @@ public class MetaTable extends Table { ...@@ -698,6 +698,7 @@ public class MetaTable extends Table {
add(rows, new String[]{"h2.clientTraceDirectory", Constants.CLIENT_TRACE_DIRECTORY}); add(rows, new String[]{"h2.clientTraceDirectory", Constants.CLIENT_TRACE_DIRECTORY});
add(rows, new String[]{"h2.scriptDirectory", Constants.SCRIPT_DIRECTORY}); add(rows, new String[]{"h2.scriptDirectory", Constants.SCRIPT_DIRECTORY});
add(rows, new String[]{"h2.maxFileRetry", "" + Constants.MAX_FILE_RETRY}); add(rows, new String[]{"h2.maxFileRetry", "" + Constants.MAX_FILE_RETRY});
add(rows, new String[]{"h2.lobAlwaysClose", "" + Constants.LOB_CLOSE_BETWEEN_READS});
break; break;
} }
case TYPE_INFO: { case TYPE_INFO: {
......
...@@ -8,11 +8,13 @@ import java.sql.SQLException; ...@@ -8,11 +8,13 @@ import java.sql.SQLException;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.index.ViewIndex; import org.h2.index.ViewIndex;
import org.h2.index.ViewIndexNew;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
...@@ -26,7 +28,8 @@ public class TableView extends Table { ...@@ -26,7 +28,8 @@ public class TableView extends Table {
private ObjectArray tables; private ObjectArray tables;
private String[] columnNames; private String[] columnNames;
private Query viewQuery; private Query viewQuery;
private ViewIndex index; private ViewIndex indexOld;
private ViewIndexNew indexNew;
private boolean recursive; private boolean recursive;
private SQLException createException; private SQLException createException;
...@@ -35,7 +38,12 @@ public class TableView extends Table { ...@@ -35,7 +38,12 @@ public class TableView extends Table {
this.querySQL = querySQL; this.querySQL = querySQL;
this.columnNames = columnNames; this.columnNames = columnNames;
this.recursive = recursive; this.recursive = recursive;
index = new ViewIndex(this, querySQL, params, recursive); int todoRemoveIndexOld;
if(Constants.INDEX_NEW) {
indexNew = new ViewIndexNew(this, querySQL, params, recursive);
} else {
indexOld = new ViewIndex(this, querySQL, params, recursive);
}
initColumnsAndTables(session); initColumnsAndTables(session);
} }
...@@ -87,7 +95,11 @@ public class TableView extends Table { ...@@ -87,7 +95,11 @@ public class TableView extends Table {
for(int i=0; i<columnNames.length; i++) { for(int i=0; i<columnNames.length; i++) {
cols[i] = new Column(columnNames[i], Value.STRING, 255, 0); cols[i] = new Column(columnNames[i], Value.STRING, 255, 0);
} }
index.setRecursive(true); if(Constants.INDEX_NEW) {
indexNew.setRecursive(true);
} else {
indexOld.setRecursive(true);
}
recursive = true; recursive = true;
createException = null; createException = null;
} }
...@@ -102,15 +114,15 @@ public class TableView extends Table { ...@@ -102,15 +114,15 @@ public class TableView extends Table {
public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException { public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException {
PlanItem item = new PlanItem(); PlanItem item = new PlanItem();
item.cost = index.getCost(session, masks); Index i2;
if(Constants.INDEX_NEW) {
Index i2 = new ViewIndex(this, index, session, masks); item.cost = indexNew.getCost(session, masks);
i2 = new ViewIndexNew(this, indexNew, session, masks);
} else {
item.cost = indexOld.getCost(session, masks);
i2 = new ViewIndex(this, indexOld, session, masks);
}
item.setIndex(i2); item.setIndex(i2);
int testing;
// item.setIndex(index);
return item; return item;
} }
...@@ -204,7 +216,8 @@ public class TableView extends Table { ...@@ -204,7 +216,8 @@ public class TableView extends Table {
removeViewFromTables(); removeViewFromTables();
super.removeChildrenAndResources(session); super.removeChildrenAndResources(session);
querySQL = null; querySQL = null;
index = null; indexNew = null;
indexOld = null;
invalidate(); invalidate();
} }
......
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
*/ */
package org.h2.tools; package org.h2.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
...@@ -86,21 +85,21 @@ public class Backup { ...@@ -86,21 +85,21 @@ public class Backup {
} }
return; return;
} }
File file = new File(zipFileName); zipFileName = FileUtils.translateFileName(zipFileName);
if(file.exists()) { if(FileUtils.exists(zipFileName)) {
file.delete(); FileUtils.delete(zipFileName);
} }
FileOutputStream out = null; OutputStream out = null;
try { try {
out = new FileOutputStream(file); out = FileUtils.openFileOutputStream(zipFileName);
ZipOutputStream zipOut = new ZipOutputStream(out); ZipOutputStream zipOut = new ZipOutputStream(out);
for(int i=0; i<list.size(); i++) { for(int i=0; i<list.size(); i++) {
String fileName = (String) list.get(i); String fileName = (String) list.get(i);
ZipEntry entry = new ZipEntry(FileUtils.getFileName(fileName)); ZipEntry entry = new ZipEntry(FileUtils.getFileName(fileName));
zipOut.putNextEntry(entry); zipOut.putNextEntry(entry);
FileInputStream in = null; InputStream in = null;
try { try {
in = new FileInputStream(fileName); in = FileUtils.openFileInputStream(fileName);
IOUtils.copyAndCloseInput(in, zipOut); IOUtils.copyAndCloseInput(in, zipOut);
} finally { } finally {
IOUtils.closeSilently(in); IOUtils.closeSilently(in);
......
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.tools;
import java.awt.Button;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemColor;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.InputStream;
import java.sql.SQLException;
import org.h2.message.Message;
import org.h2.tools.Server;
import org.h2.util.IOUtils;
import org.h2.util.StartBrowser;
public class Console implements ActionListener, MouseListener {
private static final Font FONT = new Font("Dialog", Font.PLAIN, 11);
private Server web;
public static void main(String[] args) throws Exception {
new Console().run(args);
}
private void run(String[] args) {
try {
web = Server.createWebServer(args);
web.start();
Server.createTcpServer(args).start();
Server.createOdbcServer(args).start();
} catch (SQLException e) {
if (e.getErrorCode() == Message.EXCEPTION_OPENING_PORT_1) {
System.out.println("Port is in use, maybe another server server already running on " + web.getURL());
} else {
e.printStackTrace();
}
}
try {
createMenu();
} catch (Exception e) {
e.printStackTrace();
}
// start browser anyway (even if the server is already running)
// because some people don't look at the output,
// but are wondering why nothing happens
StartBrowser.openURL(web.getURL());
if (!web.isRunning()) {
System.exit(1);
}
}
private void createMenu() throws Exception {
InputStream in = getClass().getResourceAsStream("/org/h2/res/h2.png");
byte[] imageData = IOUtils.readBytesAndClose(in, -1);
Image image = Toolkit.getDefaultToolkit().createImage(imageData);
PopupMenu menuConsole = new PopupMenu();
MenuItem itemConsole = new MenuItem("H2 Console");
itemConsole.setActionCommand("console");
itemConsole.addActionListener(this);
itemConsole.setFont(FONT);
menuConsole.add(itemConsole);
MenuItem itemExit = new MenuItem("Exit");
itemExit.setFont(FONT);
itemExit.setActionCommand("exit");
itemExit.addActionListener(this);
menuConsole.add(itemExit);
boolean showWindow;
try {
// SystemTray.isSupported();
Boolean supported = (Boolean) Class.forName("java.awt.SystemTray").
getMethod("isSupported", new Class[0]).
invoke(null, new Object[0]);
if(!supported.booleanValue()) {
showWindow = true;
}
// TrayIcon icon = new TrayIcon(image, "H2 Database Engine", menuConsole);
Object icon = Class.forName("java.awt.TrayIcon").
getConstructor(new Class[] { Image.class, String.class, PopupMenu.class }).
newInstance(new Object[] { image, "H2 Database Engine", menuConsole });
// SystemTray tray = SystemTray.getSystemTray();
Object tray = Class.forName("java.awt.SystemTray").
getMethod("getSystemTray", new Class[0]).
invoke(null, new Object[0]);
// icon.addMouseListener(this);
icon.getClass().
getMethod("addMouseListener", new Class[]{MouseListener.class}).
invoke(icon, new Object[]{this});
// tray.add(icon);
tray.getClass().
getMethod("add", new Class[] { Class.forName("java.awt.TrayIcon") }).
invoke(tray, new Object[] { icon });
showWindow = false;
} catch (Exception e) {
showWindow = true;
}
if(showWindow) {
showWindow(image);
}
}
private void showWindow(Image image) {
Frame frame = new Frame("H2 Console");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.setIconImage(image);
frame.setResizable(false);
frame.setBackground(SystemColor.control);
GridBagLayout layout = new GridBagLayout();
frame.setLayout(layout);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.EAST;
c.insets.left = 2;
c.insets.right = 2;
c.insets.top = 2;
c.insets.bottom = 2;
Label label = new Label("H2 Console URL:", Label.LEFT);
label.setFont(FONT);
c.anchor = GridBagConstraints.WEST;
c.gridwidth = GridBagConstraints.EAST;
frame.add(label, c);
TextField text = new TextField();
text.setEditable(false);
text.setFont(FONT);
text.setText(web.getURL());
text.setFocusable(false);
c.anchor = GridBagConstraints.EAST;
c.gridwidth = GridBagConstraints.REMAINDER;
frame.add(text, c);
Label label2 = new Label();
c.anchor = GridBagConstraints.WEST;
c.gridwidth = GridBagConstraints.EAST;
frame.add(label2, c);
Button startBrowser = new Button("Start Browser");
startBrowser.setFocusable(false);
startBrowser.setActionCommand("console");
startBrowser.addActionListener(this);
startBrowser.setFont(FONT);
c.anchor = GridBagConstraints.EAST;
c.gridwidth = GridBagConstraints.REMAINDER;
frame.add(startBrowser, c);
int width = 250, height = 120;
frame.setSize(width, height);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("exit")) {
System.exit(0);
} else if (e.getActionCommand().equals("console")) {
startBrowser();
}
}
private void startBrowser() {
if (web != null) {
StartBrowser.openURL(web.getURL());
}
}
public void mouseClicked(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1) {
startBrowser();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
...@@ -3,14 +3,13 @@ ...@@ -3,14 +3,13 @@
* Initial Developer: H2 Group * Initial Developer: H2 Group
*/ */
package org.h2.tools; package org.h2.tools;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.FileUtils;
/** /**
* Convert a trace file to a java class. * Convert a trace file to a java class.
...@@ -73,9 +72,9 @@ public class ConvertTraceFile { ...@@ -73,9 +72,9 @@ public class ConvertTraceFile {
* @throws IOException * @throws IOException
*/ */
private void convertFile(String traceFileName, String javaClassName, String script) throws IOException { private void convertFile(String traceFileName, String javaClassName, String script) throws IOException {
LineNumberReader reader = new LineNumberReader(new FileReader(traceFileName)); LineNumberReader reader = new LineNumberReader(FileUtils.openFileReader(traceFileName));
PrintWriter javaWriter = new PrintWriter(new FileWriter(javaClassName + ".java")); PrintWriter javaWriter = new PrintWriter(FileUtils.openFileWriter(javaClassName + ".java", false));
PrintWriter scriptWriter = new PrintWriter(new FileWriter(script)); PrintWriter scriptWriter = new PrintWriter(FileUtils.openFileWriter(script, false));
javaWriter.println("import java.io.*;"); javaWriter.println("import java.io.*;");
javaWriter.println("import java.sql.*;"); javaWriter.println("import java.sql.*;");
javaWriter.println("import java.math.*;"); javaWriter.println("import java.math.*;");
......
...@@ -4,11 +4,12 @@ ...@@ -4,11 +4,12 @@
*/ */
package org.h2.tools; package org.h2.tools;
import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.util.FileUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
/** /**
...@@ -108,7 +109,7 @@ public class CreateCluster { ...@@ -108,7 +109,7 @@ public class CreateCluster {
String scriptFile = "backup.sql"; String scriptFile = "backup.sql";
Script.execute(urlSource, user, password, scriptFile); Script.execute(urlSource, user, password, scriptFile);
RunScript.execute(urlTarget, user, password, scriptFile, null, false); RunScript.execute(urlTarget, user, password, scriptFile, null, false);
new File(scriptFile).delete(); FileUtils.delete(scriptFile);
// set the cluster to the serverlist on both databases // set the cluster to the serverlist on both databases
conn = DriverManager.getConnection(urlSource, user, password); conn = DriverManager.getConnection(urlSource, user, password);
......
...@@ -8,6 +8,7 @@ import java.io.*; ...@@ -8,6 +8,7 @@ import java.io.*;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -29,7 +30,7 @@ public class Csv implements SimpleRowSource { ...@@ -29,7 +30,7 @@ public class Csv implements SimpleRowSource {
private String fileName; private String fileName;
private InputStream in; private InputStream in;
private Reader reader; private Reader reader;
private FileOutputStream out; private OutputStream out;
private PrintWriter writer; private PrintWriter writer;
private int back; private int back;
private boolean endOfLine, endOfFile; private boolean endOfLine, endOfFile;
...@@ -43,20 +44,10 @@ public class Csv implements SimpleRowSource { ...@@ -43,20 +44,10 @@ public class Csv implements SimpleRowSource {
return new Csv(); return new Csv();
} }
/** private int writeResultSet(ResultSet rs) throws SQLException {
* Writes the result set to a file in the CSV format.
* @param fileName
* @param rs the result set
* @param charset the charset or null to use UTF-8
* @return the number of rows written
* @throws SQLException
*/
public int write(String fileName, ResultSet rs, String charset) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
init(fileName, charset);
int rows = 0;
try { try {
initWrite(); ResultSetMetaData meta = rs.getMetaData();
int rows = 0;
int columnCount = meta.getColumnCount(); int columnCount = meta.getColumnCount();
String[] row = new String[columnCount]; String[] row = new String[columnCount];
for(int i=0; i<columnCount; i++) { for(int i=0; i<columnCount; i++) {
...@@ -71,14 +62,42 @@ public class Csv implements SimpleRowSource { ...@@ -71,14 +62,42 @@ public class Csv implements SimpleRowSource {
rows++; rows++;
} }
return rows; return rows;
} catch(IOException e) {
throw convertException("IOException writing file " + fileName, e);
} finally { } finally {
close(); close();
JdbcUtils.closeSilently(rs); JdbcUtils.closeSilently(rs);
} }
} }
/**
* Writes the result set to a file in the CSV format.
* @param writer the writer
* @param rs the result set
* @return the number of rows written
* @throws SQLException, IOException
*/
public int write(Writer writer, ResultSet rs) throws SQLException, IOException {
this.writer = new PrintWriter(writer);
return writeResultSet(rs);
}
/**
* Writes the result set to a file in the CSV format.
* @param fileName the name of the csv file
* @param rs the result set
* @param charset the charset or null to use UTF-8
* @return the number of rows written
* @throws SQLException
*/
public int write(String fileName, ResultSet rs, String charset) throws SQLException {
init(fileName, charset);
try {
initWrite();
return writeResultSet(rs);
} catch(IOException e) {
throw convertException("IOException writing " + fileName, e);
}
}
/** /**
* Writes the result set of a query to a file in the CSV format. * Writes the result set of a query to a file in the CSV format.
* *
...@@ -112,16 +131,9 @@ public class Csv implements SimpleRowSource { ...@@ -112,16 +131,9 @@ public class Csv implements SimpleRowSource {
public ResultSet read(String fileName, String[] colNames, String charset) throws SQLException { public ResultSet read(String fileName, String[] colNames, String charset) throws SQLException {
init(fileName, charset); init(fileName, charset);
try { try {
columnNames = colNames; return readResultSet(colNames);
initRead();
SimpleResultSet result = new SimpleResultSet(this);
makeColumnNamesUnique();
for(int i=0; i<columnNames.length; i++) {
result.addColumn(columnNames[i], Types.VARCHAR, 255, 0);
}
return result;
} catch(IOException e) { } catch(IOException e) {
throw convertException("IOException reading file " + fileName, e); throw convertException("IOException reading " + fileName, e);
} }
} }
...@@ -134,23 +146,23 @@ public class Csv implements SimpleRowSource { ...@@ -134,23 +146,23 @@ public class Csv implements SimpleRowSource {
* @param reader the reader * @param reader the reader
* @param colNames or null if the column names should be read from the CSV file * @param colNames or null if the column names should be read from the CSV file
* @return the result set * @return the result set
* @throws SQLException * @throws SQLException, IOException
*/ */
public ResultSet read(Reader reader, String[] colNames) throws SQLException { public ResultSet read(Reader reader, String[] colNames) throws SQLException, IOException {
init(null, null); init(null, null);
try { this.reader = reader;
this.columnNames = colNames; return readResultSet(colNames);
this.reader = reader; }
initRead();
SimpleResultSet result = new SimpleResultSet(this); private ResultSet readResultSet(String[] colNames) throws SQLException, IOException {
makeColumnNamesUnique(); this.columnNames = colNames;
for(int i=0; i<columnNames.length; i++) { initRead();
result.addColumn(columnNames[i], Types.VARCHAR, 255, 0); SimpleResultSet result = new SimpleResultSet(this);
} makeColumnNamesUnique();
return result; for(int i=0; i<columnNames.length; i++) {
} catch(IOException e) { result.addColumn(columnNames[i], Types.VARCHAR, 255, 0);
throw convertException("IOException", e);
} }
return result;
} }
private void makeColumnNamesUnique() { private void makeColumnNamesUnique() {
...@@ -243,7 +255,7 @@ public class Csv implements SimpleRowSource { ...@@ -243,7 +255,7 @@ public class Csv implements SimpleRowSource {
private void initRead() throws IOException { private void initRead() throws IOException {
if(reader == null) { if(reader == null) {
try { try {
in = new FileInputStream(fileName); in = FileUtils.openFileInputStream(fileName);
BufferedInputStream i = new BufferedInputStream(in, bufferSize); BufferedInputStream i = new BufferedInputStream(in, bufferSize);
reader = new InputStreamReader(i, charset); reader = new InputStreamReader(i, charset);
// TODO what is faster, 1, 2, 1+2 // TODO what is faster, 1, 2, 1+2
......
...@@ -8,10 +8,9 @@ import java.io.BufferedInputStream; ...@@ -8,10 +8,9 @@ import java.io.BufferedInputStream;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -274,7 +273,7 @@ public class Recover implements DataHandler { ...@@ -274,7 +273,7 @@ public class Recover implements DataHandler {
fileName = fileName.substring(0, fileName.length()-3); fileName = fileName.substring(0, fileName.length()-3);
String outputFile = fileName + suffix; String outputFile = fileName + suffix;
System.out.println("Created file: " + outputFile); System.out.println("Created file: " + outputFile);
return new PrintWriter(new BufferedWriter(new FileWriter(outputFile))); return new PrintWriter(new BufferedWriter(FileUtils.openFileWriter(outputFile, false)));
} }
private void writeDataError(PrintWriter writer, String error, byte[] data, int dumpBlocks) throws IOException { private void writeDataError(PrintWriter writer, String error, byte[] data, int dumpBlocks) throws IOException {
...@@ -302,18 +301,18 @@ public class Recover implements DataHandler { ...@@ -302,18 +301,18 @@ public class Recover implements DataHandler {
} }
private void dumpLob(String fileName, boolean lobCompression) { private void dumpLob(String fileName, boolean lobCompression) {
FileOutputStream out = null; OutputStream out = null;
FileStore store = null; FileStore store = null;
int size = 0; int size = 0;
String n = fileName + (lobCompression ? ".comp" : "") + ".txt"; String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
InputStream in = null; InputStream in = null;
try { try {
out = new FileOutputStream(n); out = FileUtils.openFileOutputStream(n);
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic); store = FileStore.open(null, fileName, "r", magic);
store.init(); store.init();
in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression)); in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression, false));
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while(true) { while(true) {
int l = in.read(buffer); int l = in.read(buffer);
......
...@@ -4,16 +4,16 @@ ...@@ -4,16 +4,16 @@
*/ */
package org.h2.tools; package org.h2.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
/* /*
...@@ -67,10 +67,10 @@ public class Restore { ...@@ -67,10 +67,10 @@ public class Restore {
Restore.execute(zipFileName, dir, db, quiet); Restore.execute(zipFileName, dir, db, quiet);
} }
private static String getOriginalDbName(File file, String db) throws IOException { private static String getOriginalDbName(String fileName, String db) throws IOException {
FileInputStream in = null; InputStream in = null;
try { try {
in = new FileInputStream(file); in = FileUtils.openFileInputStream(fileName);
ZipInputStream zipIn = new ZipInputStream(in); ZipInputStream zipIn = new ZipInputStream(in);
String originalDbName = null; String originalDbName = null;
boolean multiple = false; boolean multiple = false;
...@@ -79,9 +79,9 @@ public class Restore { ...@@ -79,9 +79,9 @@ public class Restore {
if(entry == null) { if(entry == null) {
break; break;
} }
String fileName = entry.getName(); String entryName = entry.getName();
zipIn.closeEntry(); zipIn.closeEntry();
String name = FileLister.getDatabaseNameFromFileName(fileName); String name = FileLister.getDatabaseNameFromFileName(entryName);
if(name != null) { if(name != null) {
if(db.equals(name)) { if(db.equals(name)) {
originalDbName = name; originalDbName = name;
...@@ -116,20 +116,19 @@ public class Restore { ...@@ -116,20 +116,19 @@ public class Restore {
* @throws SQLException * @throws SQLException
*/ */
public static void execute(String zipFileName, String directory, String db, boolean quiet) throws SQLException { public static void execute(String zipFileName, String directory, String db, boolean quiet) throws SQLException {
FileInputStream in = null; InputStream in = null;
try { try {
File file = new File(zipFileName); if(!FileUtils.exists(zipFileName)) {
if(!file.exists()) {
throw new IOException("File not found: " + zipFileName); throw new IOException("File not found: " + zipFileName);
} }
String originalDbName = null; String originalDbName = null;
if(db != null) { if(db != null) {
originalDbName = getOriginalDbName(file, db); originalDbName = getOriginalDbName(zipFileName, db);
if(originalDbName == null) { if(originalDbName == null) {
throw new IOException("No database named " + db + " found"); throw new IOException("No database named " + db + " found");
} }
} }
in = new FileInputStream(file); in = FileUtils.openFileInputStream(zipFileName);
ZipInputStream zipIn = new ZipInputStream(in); ZipInputStream zipIn = new ZipInputStream(in);
while(true) { while(true) {
ZipEntry entry = zipIn.getNextEntry(); ZipEntry entry = zipIn.getNextEntry();
...@@ -145,9 +144,9 @@ public class Restore { ...@@ -145,9 +144,9 @@ public class Restore {
copy = true; copy = true;
} }
if(copy) { if(copy) {
FileOutputStream out = null; OutputStream out = null;
try { try {
out = new FileOutputStream(new File(directory, fileName)); out = FileUtils.openFileOutputStream(directory + "/" + fileName);
IOUtils.copy(zipIn, out); IOUtils.copy(zipIn, out);
} finally { } finally {
IOUtils.closeSilently(out); IOUtils.closeSilently(out);
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
package org.h2.tools; package org.h2.tools;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
...@@ -22,6 +20,7 @@ import java.util.Iterator; ...@@ -22,6 +20,7 @@ import java.util.Iterator;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.ClassUtils; import org.h2.util.ClassUtils;
import org.h2.util.FileUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.ScriptReader; import org.h2.util.ScriptReader;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -155,8 +154,8 @@ public class RunScript { ...@@ -155,8 +154,8 @@ public class RunScript {
} }
private static void execute(Connection conn, HashMap threadMap, String fileName, boolean continueOnError, String charsetName) throws SQLException, IOException { private static void execute(Connection conn, HashMap threadMap, String fileName, boolean continueOnError, String charsetName) throws SQLException, IOException {
InputStream in = new FileInputStream(fileName); InputStream in = FileUtils.openFileInputStream(fileName);
String path = new File(fileName).getAbsoluteFile().getParent(); String path = FileUtils.getParent(fileName);
try { try {
BufferedInputStream bin = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE); BufferedInputStream bin = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE);
InputStreamReader reader = new InputStreamReader(bin, charsetName); InputStreamReader reader = new InputStreamReader(bin, charsetName);
...@@ -177,8 +176,8 @@ public class RunScript { ...@@ -177,8 +176,8 @@ public class RunScript {
sql = sql.trim(); sql = sql.trim();
if (sql.startsWith("@") && StringUtils.toUpperEnglish(sql).startsWith("@INCLUDE")) { if (sql.startsWith("@") && StringUtils.toUpperEnglish(sql).startsWith("@INCLUDE")) {
sql = sql.substring("@INCLUDE".length()).trim(); sql = sql.substring("@INCLUDE".length()).trim();
if(!new File(sql).isAbsolute()) { if(!FileUtils.isAbsolute(sql)) {
sql = path + File.separator + sql; sql = path + "/" + sql;
} }
execute(conn, threadMap, sql, continueOnError, charsetName); execute(conn, threadMap, sql, continueOnError, charsetName);
} else if (MULTI_THREAD && sql.startsWith("/*")) { } else if (MULTI_THREAD && sql.startsWith("/*")) {
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
package org.h2.tools; package org.h2.tools;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Writer;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -15,6 +15,7 @@ import java.sql.SQLException; ...@@ -15,6 +15,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -129,12 +130,12 @@ public class Script { ...@@ -129,12 +130,12 @@ public class Script {
public static void execute(String url, String user, String password, String fileName) throws SQLException { public static void execute(String url, String user, String password, String fileName) throws SQLException {
Connection conn = null; Connection conn = null;
Statement stat = null; Statement stat = null;
FileWriter fileWriter = null; Writer fileWriter = null;
try { try {
org.h2.Driver.load(); org.h2.Driver.load();
conn = DriverManager.getConnection(url, user, password); conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement(); stat = conn.createStatement();
fileWriter = new FileWriter(fileName); fileWriter = FileUtils.openFileWriter(fileName, false);
PrintWriter writer = new PrintWriter(new BufferedWriter(fileWriter)); PrintWriter writer = new PrintWriter(new BufferedWriter(fileWriter));
ResultSet rs = stat.executeQuery("SCRIPT"); ResultSet rs = stat.executeQuery("SCRIPT");
while(rs.next()) { while(rs.next()) {
......
...@@ -7,9 +7,11 @@ package org.h2.util; ...@@ -7,9 +7,11 @@ package org.h2.util;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.io.Reader;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Properties; import java.util.Properties;
...@@ -34,6 +36,7 @@ public class FileUtils { ...@@ -34,6 +36,7 @@ public class FileUtils {
// TODO gcj: use our own UTF-8 encoder // TODO gcj: use our own UTF-8 encoder
public static RandomAccessFile openRandomAccessFile(String fileName, String mode) throws IOException { public static RandomAccessFile openRandomAccessFile(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
try { try {
return new RandomAccessFile(fileName, mode); return new RandomAccessFile(fileName, mode);
} catch(IOException e) { } catch(IOException e) {
...@@ -67,6 +70,7 @@ public class FileUtils { ...@@ -67,6 +70,7 @@ public class FileUtils {
} }
public static FileWriter openFileWriter(String fileName, boolean append) throws IOException { public static FileWriter openFileWriter(String fileName, boolean append) throws IOException {
fileName = translateFileName(fileName);
try { try {
return new FileWriter(fileName, append); return new FileWriter(fileName, append);
} catch(IOException e) { } catch(IOException e) {
...@@ -76,6 +80,7 @@ public class FileUtils { ...@@ -76,6 +80,7 @@ public class FileUtils {
} }
public static boolean fileStartsWith(String fileName, String prefix) { public static boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
if(isCaseInsensitiveFileSystem) { if(isCaseInsensitiveFileSystem) {
fileName = StringUtils.toUpperEnglish(fileName); fileName = StringUtils.toUpperEnglish(fileName);
prefix = StringUtils.toUpperEnglish(prefix); prefix = StringUtils.toUpperEnglish(prefix);
...@@ -83,13 +88,20 @@ public class FileUtils { ...@@ -83,13 +88,20 @@ public class FileUtils {
return fileName.startsWith(prefix); return fileName.startsWith(prefix);
} }
public static FileOutputStream openFileOutputStream(File file) throws IOException, SQLException { public static FileInputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
return new FileInputStream(fileName);
}
public static FileOutputStream openFileOutputStream(String fileName) throws IOException, SQLException {
fileName = translateFileName(fileName);
try { try {
File file = new File(fileName);
FileUtils.createDirs(file.getAbsolutePath()); FileUtils.createDirs(file.getAbsolutePath());
return new FileOutputStream(file); return new FileOutputStream(fileName);
} catch(IOException e) { } catch(IOException e) {
freeMemoryAndFinalize(); freeMemoryAndFinalize();
return new FileOutputStream(file); return new FileOutputStream(fileName);
} }
} }
...@@ -108,6 +120,8 @@ public class FileUtils { ...@@ -108,6 +120,8 @@ public class FileUtils {
} }
public static void rename(String oldName, String newName) throws SQLException { public static void rename(String oldName, String newName) throws SQLException {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
if(isInMemory(oldName)) { if(isInMemory(oldName)) {
MemoryFile f = getMemoryFile(oldName); MemoryFile f = getMemoryFile(oldName);
f.setName(newName); f.setName(newName);
...@@ -135,8 +149,10 @@ public class FileUtils { ...@@ -135,8 +149,10 @@ public class FileUtils {
throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null); throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
} }
public static synchronized Properties loadProperties(File file) throws IOException { public static synchronized Properties loadProperties(String fileName) throws IOException {
fileName = translateFileName(fileName);
Properties prop = new Properties(); Properties prop = new Properties();
File file = new File(fileName);
if(file.exists()) { if(file.exists()) {
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);
try { try {
...@@ -169,6 +185,7 @@ public class FileUtils { ...@@ -169,6 +185,7 @@ public class FileUtils {
} }
public static void createDirs(String fileName) throws SQLException { public static void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File f = new File(fileName); File f = new File(fileName);
if(!f.exists()) { if(!f.exists()) {
String parent = f.getParent(); String parent = f.getParent();
...@@ -187,6 +204,7 @@ public class FileUtils { ...@@ -187,6 +204,7 @@ public class FileUtils {
} }
public static boolean createNewFile(String fileName) throws SQLException { public static boolean createNewFile(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
if(exists(fileName)) { if(exists(fileName)) {
return false; return false;
...@@ -211,6 +229,7 @@ public class FileUtils { ...@@ -211,6 +229,7 @@ public class FileUtils {
} }
public static void delete(String fileName) throws SQLException { public static void delete(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
memoryFiles.remove(fileName); memoryFiles.remove(fileName);
return; return;
...@@ -242,6 +261,7 @@ public class FileUtils { ...@@ -242,6 +261,7 @@ public class FileUtils {
} }
public static String getFileName(String name) throws SQLException { public static String getFileName(String name) throws SQLException {
name = translateFileName(name);
String separator = System.getProperty("file.separator"); String separator = System.getProperty("file.separator");
String path = getParent(name) + separator; String path = getParent(name) + separator;
String fullFileName = normalize(name); String fullFileName = normalize(name);
...@@ -252,15 +272,17 @@ public class FileUtils { ...@@ -252,15 +272,17 @@ public class FileUtils {
return fileName; return fileName;
} }
public static File getFileInUserHome(String filename) { public static String getFileInUserHome(String fileName) {
String userDir = System.getProperty("user.home"); String userDir = System.getProperty("user.home");
if(userDir == null) { if(userDir == null) {
return new File(filename); return fileName;
} }
return new File(userDir, filename); File file = new File(userDir, fileName);
return file.getAbsolutePath();
} }
public static String normalize(String fileName) throws SQLException { public static String normalize(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
return fileName; return fileName;
} }
...@@ -273,6 +295,7 @@ public class FileUtils { ...@@ -273,6 +295,7 @@ public class FileUtils {
} }
public static void tryDelete(String fileName) { public static void tryDelete(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
memoryFiles.remove(fileName); memoryFiles.remove(fileName);
return; return;
...@@ -281,6 +304,7 @@ public class FileUtils { ...@@ -281,6 +304,7 @@ public class FileUtils {
} }
public static boolean isReadOnly(String fileName) { public static boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
return false; return false;
} }
...@@ -289,6 +313,7 @@ public class FileUtils { ...@@ -289,6 +313,7 @@ public class FileUtils {
} }
public static boolean exists(String fileName) { public static boolean exists(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
return memoryFiles.get(fileName) != null; return memoryFiles.get(fileName) != null;
} }
...@@ -305,6 +330,7 @@ public class FileUtils { ...@@ -305,6 +330,7 @@ public class FileUtils {
} }
public static long length(String fileName) { public static long length(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
return getMemoryFile(fileName).length(); return getMemoryFile(fileName).length();
} }
...@@ -316,6 +342,7 @@ public class FileUtils { ...@@ -316,6 +342,7 @@ public class FileUtils {
} }
public static String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException, SQLException { public static String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException, SQLException {
name = translateFileName(name);
name += "."; name += ".";
if(isInMemory(name)) { if(isInMemory(name)) {
for(int i=0;; i++) { for(int i=0;; i++) {
...@@ -344,6 +371,7 @@ public class FileUtils { ...@@ -344,6 +371,7 @@ public class FileUtils {
} }
public static String getParent(String fileName) { public static String getParent(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
return MEMORY_PREFIX; return MEMORY_PREFIX;
} }
...@@ -351,6 +379,7 @@ public class FileUtils { ...@@ -351,6 +379,7 @@ public class FileUtils {
} }
public static String[] listFiles(String path) throws SQLException { public static String[] listFiles(String path) throws SQLException {
path = translateFileName(path);
if(isInMemory(path)) { if(isInMemory(path)) {
String[] list = new String[memoryFiles.size()]; String[] list = new String[memoryFiles.size()];
MemoryFile[] l = new MemoryFile[memoryFiles.size()]; MemoryFile[] l = new MemoryFile[memoryFiles.size()];
...@@ -391,6 +420,7 @@ public class FileUtils { ...@@ -391,6 +420,7 @@ public class FileUtils {
} }
public static boolean isDirectory(String fileName) { public static boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
if(isInMemory(fileName)) { if(isInMemory(fileName)) {
// TODO inmemory: currently doesn't support directories // TODO inmemory: currently doesn't support directories
return false; return false;
...@@ -399,11 +429,13 @@ public class FileUtils { ...@@ -399,11 +429,13 @@ public class FileUtils {
} }
public static void copy(String original, String copy) throws SQLException { public static void copy(String original, String copy) throws SQLException {
original = translateFileName(original);
copy = translateFileName(copy);
FileOutputStream out = null; FileOutputStream out = null;
FileInputStream in = null; FileInputStream in = null;
try { try {
out = openFileOutputStream(new File(copy)); out = openFileOutputStream(copy);
in = new FileInputStream(new File(original)); in = openFileInputStream(original);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while(true) { while(true) {
int len = in.read(buffer); int len = in.read(buffer);
...@@ -421,6 +453,7 @@ public class FileUtils { ...@@ -421,6 +453,7 @@ public class FileUtils {
} }
public static void deleteRecursive(String fileName) throws SQLException { public static void deleteRecursive(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if(FileUtils.isDirectory(fileName)) { if(FileUtils.isDirectory(fileName)) {
String[] list = FileUtils.listFiles(fileName); String[] list = FileUtils.listFiles(fileName);
for(int i=0; list != null && i<list.length; i++) { for(int i=0; list != null && i<list.length; i++) {
...@@ -429,5 +462,40 @@ public class FileUtils { ...@@ -429,5 +462,40 @@ public class FileUtils {
} }
FileUtils.delete(fileName); FileUtils.delete(fileName);
} }
public static String translateFileName(String fileName) {
if(fileName.startsWith("~")) {
String userDir = System.getProperty("user.home");
fileName = userDir + fileName.substring(1);
}
return fileName;
}
public static boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
File file = new File(fileName);
return file.isAbsolute();
}
public static String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
File parent = new File(fileName).getAbsoluteFile();
return parent.getAbsolutePath();
}
public static long getLastModified(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).lastModified();
}
public static Reader openFileReader(String fileName) throws IOException {
fileName = translateFileName(fileName);
return new FileReader(fileName);
}
public static boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).canWrite();
}
} }
...@@ -62,7 +62,7 @@ public class Resources { ...@@ -62,7 +62,7 @@ public class Resources {
} }
String name = "/" + packageName.replace('.', '/') + "/res/" + f.getName(); String name = "/" + packageName.replace('.', '/') + "/res/" + f.getName();
// System.out.println(name+": "+f.length()); // System.out.println(name+": "+f.length());
FileInputStream in = new FileInputStream(f); InputStream in = new FileInputStream(f);
byte[] buffer = IOUtils.readBytesAndClose(in, 0); byte[] buffer = IOUtils.readBytesAndClose(in, 0);
String s = ByteUtils.convertToBinString(buffer); String s = ByteUtils.convertToBinString(buffer);
out.print(" Resources.add(" + StringUtils.quoteJavaString(name) + ", "); out.print(" Resources.add(" + StringUtils.quoteJavaString(name) + ", ");
......
...@@ -456,10 +456,10 @@ public class ValueLob extends Value { ...@@ -456,10 +456,10 @@ public class ValueLob extends Value {
public int hashCode() { public int hashCode() {
if (hash == 0) { if (hash == 0) {
int todo; if(precision > 4096) {
// if(precision > 4096) { // TODO: should calculate the hash code when saving, and store it in the data file
// return (int)(precision ^ (precision >> 32)); return (int)(precision ^ (precision >> 32));
// } }
try { try {
hash = ByteUtils.getByteArrayHash(getBytes()); hash = ByteUtils.getByteArrayHash(getBytes());
} catch(SQLException e) { } catch(SQLException e) {
...@@ -496,7 +496,8 @@ public class ValueLob extends Value { ...@@ -496,7 +496,8 @@ public class ValueLob extends Value {
return new ByteArrayInputStream(small); return new ByteArrayInputStream(small);
} }
FileStore store = handler.openFile(fileName, "r", true); FileStore store = handler.openFile(fileName, "r", true);
return new BufferedInputStream(new FileStoreInputStream(store, handler, compression), Constants.IO_BUFFER_SIZE); boolean alwaysClose = Constants.LOB_CLOSE_BETWEEN_READS;
return new BufferedInputStream(new FileStoreInputStream(store, handler, compression, alwaysClose), Constants.IO_BUFFER_SIZE);
} }
public void set(PreparedStatement prep, int parameterIndex) throws SQLException { public void set(PreparedStatement prep, int parameterIndex) throws SQLException {
......
...@@ -7,7 +7,6 @@ package org.h2.test; ...@@ -7,7 +7,6 @@ package org.h2.test;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
import org.h2.engine.Constants;
import org.h2.server.TcpServer; import org.h2.server.TcpServer;
import org.h2.test.jdbc.*; import org.h2.test.jdbc.*;
import org.h2.test.jdbc.xa.TestXA; import org.h2.test.jdbc.xa.TestXA;
...@@ -59,7 +58,7 @@ public class TestAll { ...@@ -59,7 +58,7 @@ public class TestAll {
/* /*
Random test: Random test:
cd bin cd bin
del *.db del *.db
start cmd /k "java -cp .;%H2DRIVERS% org.h2.test.TestAll join >testJoin.txt" start cmd /k "java -cp .;%H2DRIVERS% org.h2.test.TestAll join >testJoin.txt"
...@@ -91,22 +90,15 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -91,22 +90,15 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
TestAll test = new TestAll(); TestAll test = new TestAll();
test.printSystem(); test.printSystem();
/* /*
Before you ask support:
Query is slow
- Run ANALYSE (see documentation for details)
Negative dictionary: Set h2.indexNew to false
Please note that
timer test testHalt
PostgreSQL: support ~ dir
--SET search_path = public, pg_catalog;
--id serial NOT NULL,
Mail http://sf.net/projects/samooha Mail http://sf.net/projects/samooha
...@@ -119,7 +111,7 @@ h2\src\docsrc\html\images\SQLInjection.txt ...@@ -119,7 +111,7 @@ h2\src\docsrc\html\images\SQLInjection.txt
D:\pictures\2007-email D:\pictures\2007-email
ftp: problem with multithreading? ftp server: problem with multithreading?
send http://thecodist.com/fiche/thecodist/article/sql-injections-how-not-to-get-stuck to JavaWorld, TheServerSide, send http://thecodist.com/fiche/thecodist/article/sql-injections-how-not-to-get-stuck to JavaWorld, TheServerSide,
MySQL, PostgreSQL MySQL, PostgreSQL
...@@ -129,38 +121,6 @@ try out, find bugs ...@@ -129,38 +121,6 @@ try out, find bugs
Mail P2P Mail P2P
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(ID INT PRIMARY KEY);
@LOOP 1000 INSERT INTO TEST VALUES(?);
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE ID=10;
@LOOP 1000 SELECT * FROM TEST_VIEW WHERE ID=?;
@LOOP 1000 SELECT * FROM TEST WHERE ID=?;
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(
PERSON_ID INT PRIMARY KEY,
NAME VARCHAR,
LOWER_NAME VARCHAR AS LOWER(NAME)
);
CREATE INDEX IDX_NAME ON TEST(LOWER_NAME);
EXPLAIN SELECT * FROM TEST WHERE LOWER_NAME LIKE '%';
EXPLAIN SELECT * FROM TEST WHERE LOWER_NAME LIKE '%' ORDER BY LOWER_NAME;
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE LOWER_NAME LIKE '%';
EXPLAIN SELECT * FROM TEST_VIEW WHERE LOWER_NAME LIKE '%' ORDER BY LOWER_NAME;
DROP TABLE TEST;
DROP VIEW TEST_VIEW;
CREATE TABLE TEST(ID INT PRIMARY KEY);
@LOOP 1000 INSERT INTO TEST VALUES(?);
CREATE VIEW TEST_VIEW AS SELECT * FROM TEST;
EXPLAIN SELECT * FROM TEST_VIEW WHERE ID=10;
@LOOP 1000 SELECT * FROM TEST_VIEW WHERE ID=?;
@LOOP 1000 SELECT * FROM TEST WHERE ID=?;
Currently there is no such feature, however it is quite simple to add a user defined function Currently there is no such feature, however it is quite simple to add a user defined function
READ_TEXT(fileName String) returning a CLOB. The performance would probably not be optimal, READ_TEXT(fileName String) returning a CLOB. The performance would probably not be optimal,
but it should work. I am not sure if this will read the CLOB in memory however. but it should work. I am not sure if this will read the CLOB in memory however.
...@@ -173,25 +133,37 @@ Add a setting to allow BigDecimal extensions ...@@ -173,25 +133,37 @@ Add a setting to allow BigDecimal extensions
Send SQL Injection solution proposal to PostgreSQL, MySQL, Derby, HSQLDB,... Send SQL Injection solution proposal to PostgreSQL, MySQL, Derby, HSQLDB,...
Improve ACID documentation (durability problem)
Improve LOB in directories performance Improve LOB in directories performance
Improve documentation for MAX_LENGTH_INPLACE_LOB Improve documentation for MAX_LENGTH_INPLACE_LOB
Convert SQL-injection-2.txt to html document, include SQLInjection.java sample Convert SQL-injection-2.txt to html document, include SQLInjection.java sample
Integrate patches from Pavel Ganelin: www.dullesopen.com/software/h2-database-03-04-07-mod.src.zip Integrate patches from Pavel Ganelin: www.dullesopen.com/software/h2-database-03-04-07-mod.src.zip
Test Eclipse DTP 1.5 (HSQLDB / H2 connection bug fixed) Test Eclipse DTP 1.5 (HSQLDB / H2 connection bug fixed)
Automate real power off tests Automate real power off tests
how to make -baseDir work for H2 Console? how to make -baseDir work for H2 Console?
Maybe add a little bit AdSense Maybe add a little bit AdSense
Custom Captcha for the forum, to protect against spam bots (required for Google Code?) Custom Captcha for the forum, to protect against spam bots (required for Google Code?)
http://db.apache.org/ddlutils/ (write a H2 driver)
Negative dictionary:
Please note that
timer test
PostgreSQL compatibility:
--SET search_path = public, pg_catalog;
--id serial NOT NULL,
CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ] CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ]
[ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
[ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ] [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
http://db.apache.org/ddlutils/ (write a H2 driver)
ant docs doesn't work
*/ */
/* /*
...@@ -260,7 +232,6 @@ SELECT ID AS A FROM TEST GROUP BY ID HAVING A>0; ...@@ -260,7 +232,6 @@ SELECT ID AS A FROM TEST GROUP BY ID HAVING A>0;
SELECT COUNT(*) AS A FROM TEST GROUP BY ID HAVING A>0; SELECT COUNT(*) AS A FROM TEST GROUP BY ID HAVING A>0;
-- Yes: MySQL, HSQLDB -- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby -- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
*/ */
// TODO: fix Hibernate dialect bug / Bordea Felix (lost email) // TODO: fix Hibernate dialect bug / Bordea Felix (lost email)
......
...@@ -7,7 +7,6 @@ package org.h2.test.db; ...@@ -7,7 +7,6 @@ package org.h2.test.db;
import java.io.File; import java.io.File;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.Statement; import java.sql.Statement;
...@@ -36,7 +35,6 @@ public class TestCsv extends TestBase { ...@@ -36,7 +35,6 @@ public class TestCsv extends TestBase {
checkFalse(rs.next()); checkFalse(rs.next());
new File(BASE_DIR+"/test.csv").delete(); new File(BASE_DIR+"/test.csv").delete();
int testing;
// PreparedStatement prep = conn.prepareStatement("select * from csvread(?, null, ?, ?)"); // PreparedStatement prep = conn.prepareStatement("select * from csvread(?, null, ?, ?)");
// prep.setString(1, BASE_DIR+"/test.csv"); // prep.setString(1, BASE_DIR+"/test.csv");
// prep.setString(2, "utf-8"); // prep.setString(2, "utf-8");
......
...@@ -15,10 +15,12 @@ import java.sql.Connection; ...@@ -15,10 +15,12 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint; import java.sql.Savepoint;
import java.sql.Statement; import java.sql.Statement;
import java.util.Random; import java.util.Random;
import org.h2.engine.Constants;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -33,6 +35,7 @@ public class TestLob extends TestBase { ...@@ -33,6 +35,7 @@ public class TestLob extends TestBase {
if(config.memory) { if(config.memory) {
return; return;
} }
testLobNoClose();
testLobTransactions(10); testLobTransactions(10);
testLobTransactions(10000); testLobTransactions(10000);
testLobRollbackStop(); testLobRollbackStop();
...@@ -51,6 +54,38 @@ public class TestLob extends TestBase { ...@@ -51,6 +54,38 @@ public class TestLob extends TestBase {
testJavaObject(); testJavaObject();
} }
private void testLobNoClose() throws Exception {
if(config.logMode == 0 || config.networked) {
return;
}
deleteDb("lob");
Connection conn = reconnect(null);
conn.createStatement().execute("CREATE TABLE TEST(ID IDENTITY, DATA CLOB)");
conn.createStatement().execute("INSERT INTO TEST VALUES(1, SPACE(10000))");
ResultSet rs = conn.createStatement().executeQuery("SELECT DATA FROM TEST");
rs.next();
Constants.LOB_CLOSE_BETWEEN_READS = true;
Reader in = rs.getCharacterStream(1);
in.read();
conn.createStatement().execute("DELETE FROM TEST");
Constants.LOB_CLOSE_BETWEEN_READS = false;
conn.createStatement().execute("INSERT INTO TEST VALUES(1, SPACE(10000))");
rs = conn.createStatement().executeQuery("SELECT DATA FROM TEST");
rs.next();
in = rs.getCharacterStream(1);
in.read();
conn.setAutoCommit(false);
try {
conn.createStatement().execute("DELETE FROM TEST");
conn.commit();
error("Error expected");
} catch(SQLException e) {
checkNotGeneralException(e);
}
conn.rollback();
conn.close();
}
private void testLobTransactions(int spaceLen) throws Exception { private void testLobTransactions(int spaceLen) throws Exception {
if(config.logMode == 0) { if(config.logMode == 0) {
return; return;
......
...@@ -824,9 +824,9 @@ create memory table a(k10 blob(10k), m20 blob(20m), g30 clob(30g)); ...@@ -824,9 +824,9 @@ create memory table a(k10 blob(10k), m20 blob(20m), g30 clob(30g));
script NODATA NOPASSWORDS NOSETTINGS drop; script NODATA NOPASSWORDS NOSETTINGS drop;
> SCRIPT > SCRIPT
> ----------------------------------------------------------------------------------------------------- > ------------------------------------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM PUBLIC.A > -- 0 = SELECT COUNT(*) FROM PUBLIC.A
> CREATE MEMORY TABLE PUBLIC.A( K10 BLOB(10240), M20 BLOB(20971520), G30 CLOB(2147483647) ) > CREATE MEMORY TABLE PUBLIC.A( K10 BLOB(10240), M20 BLOB(20971520), G30 CLOB(32212254720) )
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN > CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> DROP TABLE IF EXISTS PUBLIC.A > DROP TABLE IF EXISTS PUBLIC.A
> rows: 4 > rows: 4
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论