提交 4ba52d30 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 ad1a436f
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
</target> </target>
<target name="switchSourcePrepare" depends="clean"> <target name="switchSourcePrepare" depends="clean">
<javac srcdir="src/tools" destdir="bin" debug="true" debuglevel="lines,source" includes="org/h2/build/code/SwitchSource.java"/> <javac source="1.4" srcdir="src/tools" destdir="bin" debug="true" debuglevel="lines,source" includes="org/h2/build/code/SwitchSource.java"/>
</target> </target>
<target name="switchSourceAndroid" depends="switchSourcePrepare"> <target name="switchSourceAndroid" depends="switchSourcePrepare">
......
...@@ -58,6 +58,8 @@ Advanced Topics ...@@ -58,6 +58,8 @@ Advanced Topics
Settings Read from System Properties</a><br /> Settings Read from System Properties</a><br />
<a href="#server_bind_address"> <a href="#server_bind_address">
Setting the Server Bind Address</a><br /> Setting the Server Bind Address</a><br />
<a href="#limitations">
Limitations</a><br />
<a href="#glossary_links"> <a href="#glossary_links">
Glossary and Links</a><br /> Glossary and Links</a><br />
...@@ -1061,6 +1063,33 @@ This setting is used for both regular server sockets and for SSL server sockets. ...@@ -1061,6 +1063,33 @@ This setting is used for both regular server sockets and for SSL server sockets.
IPv4 and IPv6 address formats are supported. IPv4 and IPv6 address formats are supported.
</p> </p>
<br /><a name="limitations"></a>
<h2>Limitations</h2>
<p>
This database has the following known limitations:
</p>
<ul>
<li>The maximum file size is currently 256 GB for the data, and 256 GB for the index.
This number is excluding BLOB and CLOB data:
Every CLOB or BLOB can be up to 256 GB as well.
</li><li>The maximum file size for FAT or FAT32 file systems is 4 GB. That means when using FAT or FAT32,
the limit is 4 GB for the data. This is the limitation of the file system, and this database does not provide a
workaround for this problem. The suggested solution is to use another file system.
</li><li>There is a limit on the complexity of SQL statements.
Statements of the following form will result in a stack overflow exception:
<pre>
SELECT * FROM DUAL WHERE X = 1
OR X = 2 OR X = 2 OR X = 2 OR X = 2 OR X = 2
-- repeat previous line 500 times --
</pre>
</li><li>There is no limit for the following entities, except the memory and storage capacity:
maximum identifier length, maximum number of tables, maximum number of columns,
maximum number of indexes, maximum number of parameters,
maximum number of triggers, and maximum number of other database objects.
</li><li>For limitations on data types, see the documentation of the respective Java data type
or the data type documentation of this database.
</ul>
<br /><a name="glossary_links"></a> <br /><a name="glossary_links"></a>
<h2>Glossary and Links</h2> <h2>Glossary and Links</h2>
<table><tr><th>Term</th><th>Description</th></tr> <table><tr><th>Term</th><th>Description</th></tr>
......
...@@ -162,7 +162,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader { ...@@ -162,7 +162,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
public void flush(Session session) throws SQLException { public void flush(Session session) throws SQLException {
lastChange = 0; lastChange = 0;
if (storage != null) { if (storage != null) {
storage.flushFile(); storage.getDiskFile().flush();
if (!database.getReadOnly()) { if (!database.getReadOnly()) {
deletePage(session, head); deletePage(session, head);
// if we log index changes now, then the index is consistent // if we log index changes now, then the index is consistent
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
90023=Feld {0} darf nicht NULL nicht erlauben 90023=Feld {0} darf nicht NULL nicht erlauben
90024=Fehler beim Umbenennen der Datei {0} nach {1} 90024=Fehler beim Umbenennen der Datei {0} nach {1}
90025=Kann Datei {0} nicht l\u00F6schen 90025=Kann Datei {0} nicht l\u00F6schen
90026=Serialisierung fehlgeschlagen, Grund\: {} 90026=Serialisierung fehlgeschlagen, Grund\: {0}
90027=De-Serialisierung fehlgeschlagen, Grund\: {1} 90027=De-Serialisierung fehlgeschlagen, Grund\: {1}
90028=Eingabe/Ausgabe Fehler\: {0} 90028=Eingabe/Ausgabe Fehler\: {0}
90029=Im Moment nicht auf einer ver\u00E4nderbaren Zeile 90029=Im Moment nicht auf einer ver\u00E4nderbaren Zeile
......
...@@ -1469,14 +1469,15 @@ Number with fixed precision and scale. ...@@ -1469,14 +1469,15 @@ Number with fixed precision and scale.
[- | +] digit [...] [- | +] digit [...]
[. digit [...] [E [- | +] exponentDigit [...] ]] [. digit [...] [E [- | +] exponentDigit [...] ]]
"," ","
There is no minimum or maximum number. The limitations are the same as for the Java data type Double.
"," ","
-1.4e-10 -1.4e-10
" "
"Other Grammar","Date"," "Other Grammar","Date","
DATE 'yyyy-MM-dd' DATE 'yyyy-MM-dd'
"," ","
A date literal. A date literal. The limitations are the same as for the Java data type java.sql.Date, but
for compatibility with other databases the suggested minimum and maximum years are 0001 and 9999.
"," ","
DATE '2004-12-31' DATE '2004-12-31'
" "
...@@ -1490,7 +1491,8 @@ TIME '23:59:59' ...@@ -1490,7 +1491,8 @@ TIME '23:59:59'
"Other Grammar","Timestamp"," "Other Grammar","Timestamp","
TIMESTAMP 'yyyy-MM-dd hh:mm:ss[.nnnnnnnnn]' TIMESTAMP 'yyyy-MM-dd hh:mm:ss[.nnnnnnnnn]'
"," ","
A timestamp literal. A timestamp literal. The limitations are the same as for the Java data type java.sql.Timestamp, but
for compatibility with other databases the suggested minimum and maximum years are 0001 and 9999.
"," ","
TIMESTAMP '2005-12-31 23:59:59' TIMESTAMP '2005-12-31 23:59:59'
" "
......
...@@ -75,11 +75,11 @@ public class DiskFile implements CacheWriter { ...@@ -75,11 +75,11 @@ public class DiskFile implements CacheWriter {
*/ */
public static final int BLOCK_SIZE = 128; public static final int BLOCK_SIZE = 128;
// TODO storage: header should probably be 4 KB or so
// (to match block size of operating system)
private static final int OFFSET = FileStore.HEADER_LENGTH; private static final int OFFSET = FileStore.HEADER_LENGTH;
private static final int FREE_PAGE = -1; private static final int FREE_PAGE = -1;
// TODO storage: header should probably be 4 KB or so
// (to match block size of operating system)
private Database database; private Database database;
private String fileName; private String fileName;
private FileStore file; private FileStore file;
...@@ -183,6 +183,11 @@ public class DiskFile implements CacheWriter { ...@@ -183,6 +183,11 @@ public class DiskFile implements CacheWriter {
} }
} }
/**
* Get the 'storage allocation table' of this file.
*
* @return the table
*/
public byte[] getSummary() throws SQLException { public byte[] getSummary() throws SQLException {
synchronized (database) { synchronized (database) {
try { try {
...@@ -241,6 +246,11 @@ public class DiskFile implements CacheWriter { ...@@ -241,6 +246,11 @@ public class DiskFile implements CacheWriter {
return true; return true;
} }
/**
* Initialize the the 'storage allocation table' of this file from a given byte array.
*
* @param summary the storage allocation table
*/
public void initFromSummary(byte[] summary) { public void initFromSummary(byte[] summary) {
synchronized (database) { synchronized (database) {
if (summary == null || summary.length == 0) { if (summary == null || summary.length == 0) {
...@@ -339,7 +349,9 @@ public class DiskFile implements CacheWriter { ...@@ -339,7 +349,9 @@ public class DiskFile implements CacheWriter {
} }
} }
/**
* Read the 'storage allocation table' from the file if required.
*/
public void init() throws SQLException { public void init() throws SQLException {
synchronized (database) { synchronized (database) {
if (init) { if (init) {
...@@ -389,6 +401,9 @@ public class DiskFile implements CacheWriter { ...@@ -389,6 +401,9 @@ public class DiskFile implements CacheWriter {
} }
} }
/**
* Flush all pending changes to disk.
*/
public void flush() throws SQLException { public void flush() throws SQLException {
synchronized (database) { synchronized (database) {
database.checkPowerOff(); database.checkPowerOff();
...@@ -440,6 +455,9 @@ public class DiskFile implements CacheWriter { ...@@ -440,6 +455,9 @@ public class DiskFile implements CacheWriter {
// } // }
// } // }
/**
* Flush all pending changes and close the file.
*/
public void close() throws SQLException { public void close() throws SQLException {
synchronized (database) { synchronized (database) {
SQLException closeException = null; SQLException closeException = null;
...@@ -678,6 +696,12 @@ public class DiskFile implements CacheWriter { ...@@ -678,6 +696,12 @@ public class DiskFile implements CacheWriter {
return pageOwners.get(page); return pageOwners.get(page);
} }
/**
* Set the owner of a page.
*
* @param page the page id
* @param the storage id of this page
*/
public void setPageOwner(int page, int storageId) throws SQLException { public void setPageOwner(int page, int storageId) throws SQLException {
int old = pageOwners.get(page); int old = pageOwners.get(page);
if (old == storageId) { if (old == storageId) {
...@@ -721,6 +745,9 @@ public class DiskFile implements CacheWriter { ...@@ -721,6 +745,9 @@ public class DiskFile implements CacheWriter {
} }
} }
/**
* Close the file and delete it.
*/
public void delete() throws SQLException { public void delete() throws SQLException {
synchronized (database) { synchronized (database) {
try { try {
...@@ -749,6 +776,12 @@ public class DiskFile implements CacheWriter { ...@@ -749,6 +776,12 @@ public class DiskFile implements CacheWriter {
// return start; // return start;
// } // }
/**
* Write a record to the file immediately.
* This method is called by the cache, and when flushing pending changes.
*
* @param obj the record to write
*/
public void writeBack(CacheObject obj) throws SQLException { public void writeBack(CacheObject obj) throws SQLException {
synchronized (database) { synchronized (database) {
writeCount++; writeCount++;
...@@ -769,8 +802,10 @@ public class DiskFile implements CacheWriter { ...@@ -769,8 +802,10 @@ public class DiskFile implements CacheWriter {
} }
} }
/* /**
* Must be synchronized externally * Get the usage bits. The bit field must be synchronized externally.
*
* @return the bit field of used blocks.
*/ */
BitField getUsed() { BitField getUsed() {
return used; return used;
...@@ -901,11 +936,11 @@ public class DiskFile implements CacheWriter { ...@@ -901,11 +936,11 @@ public class DiskFile implements CacheWriter {
} }
} }
public int getRecordOverhead() { int getRecordOverhead() {
return recordOverhead; return recordOverhead;
} }
public void truncateStorage(Session session, Storage storage, IntArray pages) throws SQLException { void truncateStorage(Session session, Storage storage, IntArray pages) throws SQLException {
synchronized (database) { synchronized (database) {
int storageId = storage.getId(); int storageId = storage.getId();
// make sure the cache records of this storage are not flushed to disk // make sure the cache records of this storage are not flushed to disk
......
...@@ -27,11 +27,28 @@ import org.h2.util.TempFileDeleter; ...@@ -27,11 +27,28 @@ import org.h2.util.TempFileDeleter;
*/ */
public class FileStore { public class FileStore {
/**
* The size of the file header in bytes.
*/
public static final int HEADER_LENGTH = 3 * Constants.FILE_BLOCK_SIZE; public static final int HEADER_LENGTH = 3 * Constants.FILE_BLOCK_SIZE;
/**
* An empty buffer to speed up extending the file (it seems that writing 0
* bytes is faster then calling setLength).
*/
protected static final byte[] EMPTY = new byte[16 * 1024]; protected static final byte[] EMPTY = new byte[16 * 1024];
/**
* The file name.
*/
protected String name; protected String name;
/**
* The callback object is responsible to check access rights, and free up
* disk space if required.
*/
protected DataHandler handler; protected DataHandler handler;
private byte[] magic; private byte[] magic;
private FileObject file; private FileObject file;
private long filePos; private long filePos;
...@@ -41,6 +58,14 @@ public class FileStore { ...@@ -41,6 +58,14 @@ public class FileStore {
private boolean synchronousMode; private boolean synchronousMode;
private String mode; private String mode;
/**
* Create a new file using the given settings.
*
* @param handler the callback object
* @param name the file name
* @param mode the access mode ("r", "rw", "rws", "rwd")
* @param magic the magic file header
*/
protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException { protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
FileSystem fs = FileSystem.getInstance(name); FileSystem fs = FileSystem.getInstance(name);
this.handler = handler; this.handler = handler;
...@@ -131,18 +156,22 @@ public class FileStore { ...@@ -131,18 +156,22 @@ public class FileStore {
this.checkedWriting = value; this.checkedWriting = value;
} }
protected void checkWritingAllowed() throws SQLException { private void checkWritingAllowed() throws SQLException {
if (handler != null && checkedWriting) { if (handler != null && checkedWriting) {
handler.checkWritingAllowed(); handler.checkWritingAllowed();
} }
} }
protected void checkPowerOff() throws SQLException { private void checkPowerOff() throws SQLException {
if (handler != null) { if (handler != null) {
handler.checkPowerOff(); handler.checkPowerOff();
} }
} }
/**
* Initialize the file. This method will write or check the file header if
* required.
*/
public void init() throws SQLException { public void init() throws SQLException {
int len = Constants.FILE_BLOCK_SIZE; int len = Constants.FILE_BLOCK_SIZE;
byte[] salt; byte[] salt;
...@@ -175,6 +204,9 @@ public class FileStore { ...@@ -175,6 +204,9 @@ public class FileStore {
} }
} }
/**
* Close the file.
*/
public void close() throws IOException { public void close() throws IOException {
if (file != null) { if (file != null) {
try { try {
...@@ -186,6 +218,10 @@ public class FileStore { ...@@ -186,6 +218,10 @@ public class FileStore {
} }
} }
/**
* Close the file without throwing any exceptions. Exceptions are simply
* ignored.
*/
public void closeSilently() { public void closeSilently() {
try { try {
close(); close();
...@@ -194,6 +230,9 @@ public class FileStore { ...@@ -194,6 +230,9 @@ public class FileStore {
} }
} }
/**
* Close the file (ignoring exceptions) and delete the file.
*/
public void closeAndDeleteSilently() { public void closeAndDeleteSilently() {
if (file != null) { if (file != null) {
closeSilently(); closeSilently();
...@@ -202,10 +241,24 @@ public class FileStore { ...@@ -202,10 +241,24 @@ public class FileStore {
} }
} }
/**
* Read a number of bytes without decrypting.
*
* @param b the target buffer
* @param off the offset
* @param len the number of bytes to read
*/
protected void readFullyDirect(byte[] b, int off, int len) throws SQLException { protected void readFullyDirect(byte[] b, int off, int len) throws SQLException {
readFully(b, off, len); readFully(b, off, len);
} }
/**
* Read a number of bytes.
*
* @param b the target buffer
* @param off the offset
* @param len the number of bytes to read
*/
public void readFully(byte[] b, int off, int len) throws SQLException { public void readFully(byte[] b, int off, int len) throws SQLException {
if (SysProperties.CHECK && len < 0) { if (SysProperties.CHECK && len < 0) {
throw Message.getInternalError("read len " + len); throw Message.getInternalError("read len " + len);
...@@ -222,6 +275,11 @@ public class FileStore { ...@@ -222,6 +275,11 @@ public class FileStore {
filePos += len; filePos += len;
} }
/**
* Go to the specified file location.
*
* @param pos the location
*/
public void seek(long pos) throws SQLException { public void seek(long pos) throws SQLException {
if (SysProperties.CHECK && pos % Constants.FILE_BLOCK_SIZE != 0) { if (SysProperties.CHECK && pos % Constants.FILE_BLOCK_SIZE != 0) {
throw Message.getInternalError("unaligned seek " + name + " pos " + pos); throw Message.getInternalError("unaligned seek " + name + " pos " + pos);
...@@ -236,10 +294,24 @@ public class FileStore { ...@@ -236,10 +294,24 @@ public class FileStore {
} }
} }
/**
* Write a number of bytes without encrypting.
*
* @param b the source buffer
* @param off the offset
* @param len the number of bytes to write
*/
protected void writeDirect(byte[] b, int off, int len) throws SQLException { protected void writeDirect(byte[] b, int off, int len) throws SQLException {
write(b, off, len); write(b, off, len);
} }
/**
* Write a number of bytes.
*
* @param b the source buffer
* @param off the offset
* @param len the number of bytes to write
*/
public void write(byte[] b, int off, int len) throws SQLException { public void write(byte[] b, int off, int len) throws SQLException {
if (SysProperties.CHECK && len < 0) { if (SysProperties.CHECK && len < 0) {
throw Message.getInternalError("read len " + len); throw Message.getInternalError("read len " + len);
...@@ -289,6 +361,11 @@ public class FileStore { ...@@ -289,6 +361,11 @@ public class FileStore {
file.seek(pos); file.seek(pos);
} }
/**
* Set the length of the file. This will expand or shrink the file.
*
* @param newLength the new file size
*/
public void setLength(long newLength) throws SQLException { public void setLength(long newLength) throws SQLException {
if (SysProperties.CHECK && newLength % Constants.FILE_BLOCK_SIZE != 0) { if (SysProperties.CHECK && newLength % Constants.FILE_BLOCK_SIZE != 0) {
throw Message.getInternalError("unaligned setLength " + name + " pos " + newLength); throw Message.getInternalError("unaligned setLength " + name + " pos " + newLength);
...@@ -315,6 +392,11 @@ public class FileStore { ...@@ -315,6 +392,11 @@ public class FileStore {
} }
} }
/**
* Get the file size in bytes.
*
* @return the file size
*/
public long length() throws SQLException { public long length() throws SQLException {
try { try {
long len = fileLength; long len = fileLength;
...@@ -336,6 +418,11 @@ public class FileStore { ...@@ -336,6 +418,11 @@ public class FileStore {
} }
} }
/**
* Get the current location of the file pointer.
*
* @return the location
*/
public long getFilePointer() throws SQLException { public long getFilePointer() throws SQLException {
if (SysProperties.CHECK2) { if (SysProperties.CHECK2) {
try { try {
...@@ -349,6 +436,10 @@ public class FileStore { ...@@ -349,6 +436,10 @@ public class FileStore {
return filePos; return filePos;
} }
/**
* Call fsync. Depending on the operating system and hardware, this may or
* may not in fact write the changes.
*/
public void sync() { public void sync() {
try { try {
file.sync(); file.sync();
...@@ -357,24 +448,42 @@ public class FileStore { ...@@ -357,24 +448,42 @@ public class FileStore {
} }
} }
/**
* Automatically delete the file once it is no longer in use.
*/
public void autoDelete() { public void autoDelete() {
autoDeleteReference = TempFileDeleter.addFile(name, this); autoDeleteReference = TempFileDeleter.addFile(name, this);
} }
/**
* No longer automatically delete the file once it is no longer in use.
*/
public void stopAutoDelete() { public void stopAutoDelete() {
TempFileDeleter.stopAutoDelete(autoDeleteReference, name); TempFileDeleter.stopAutoDelete(autoDeleteReference, name);
autoDeleteReference = null; autoDeleteReference = null;
} }
/**
* Check if the file is encrypted.
*
* @return true if it is
*/
public boolean isEncrypted() { public boolean isEncrypted() {
return false; return false;
} }
/**
* Close the file. The file may later be re-opened using openFile.
*/
public void closeFile() throws IOException { public void closeFile() throws IOException {
file.close(); file.close();
file = null; file = null;
} }
/**
* Re-open the file. The file pointer will be reset to the previous
* location.
*/
public void openFile() throws IOException { public void openFile() throws IOException {
if (file == null) { if (file == null) {
file = FileSystem.getInstance(name).openFileObject(name, mode); file = FileSystem.getInstance(name).openFileObject(name, mode);
......
...@@ -312,10 +312,6 @@ public class Storage { ...@@ -312,10 +312,6 @@ public class Storage {
file.writeBack(rec); file.writeBack(rec);
} }
public void flushFile() throws SQLException {
file.flush();
}
/** /**
* Get the overhead to store a record (header data) in number of bytes. * Get the overhead to store a record (header data) in number of bytes.
* *
......
...@@ -14,7 +14,7 @@ import org.h2.constant.SysProperties; ...@@ -14,7 +14,7 @@ import org.h2.constant.SysProperties;
/** /**
* The object array is basically the same as ArrayList. * The object array is basically the same as ArrayList.
* It is a bit faster than ArrayList in some java versions. * It is a bit faster than ArrayList in some versions of Java.
*/ */
public class ObjectArray { public class ObjectArray {
private static final int SIZE_INIT = 4, SIZE_SHRINK = 256; private static final int SIZE_INIT = 4, SIZE_SHRINK = 256;
......
...@@ -16,7 +16,6 @@ import java.sql.SQLException; ...@@ -16,7 +16,6 @@ import java.sql.SQLException;
public abstract class Tool { public abstract class Tool {
protected PrintStream out = System.out; protected PrintStream out = System.out;
protected PrintStream err = System.err;
/** /**
* Sets the standard output stream. * Sets the standard output stream.
......
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright 2004-2008 H2 Group. Copyright 2004-2008 H2 Group.
Multiple-Licensed under the H2 License, Version 1.0, Multiple-Licensed under the H2 License, Version 1.0,
......
...@@ -29,7 +29,7 @@ public class MergeDocs { ...@@ -29,7 +29,7 @@ public class MergeDocs {
// the order of pages is important here // the order of pages is important here
String[] pages = { "quickstart.html", "installation.html", "tutorial.html", "features.html", String[] pages = { "quickstart.html", "installation.html", "tutorial.html", "features.html",
"performance.html", "advanced.html", "grammar.html", "functions.html", "datatypes.html", "build.html", "performance.html", "advanced.html", "grammar.html", "functions.html", "datatypes.html", "build.html",
"history.html", "faq.html", "license.html" }; "history.html", "faq.html" };
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
for (int i = 0; i < pages.length; i++) { for (int i = 0; i < pages.length; i++) {
String fileName = pages[i]; String fileName = pages[i];
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论