提交 03a6507d authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 6b5d8b92
......@@ -67,12 +67,12 @@ The other targets may be used as well.
<h3>Using a Central Repository</h3>
<p>
You can include the database in your Maven 2 project as a dependency.
The version is currently 1.0.&lt;year&gt;&lt;month&gt;&lt;day&gt;. Example:
Example:
<pre>
&lt;dependency&gt;
&lt;groupId&gt;com.h2database&lt;/groupId&gt;
&lt;artifactId&gt;h2&lt;/artifactId&gt;
&lt;version&gt;1.0.20070617&lt;/version&gt;
&lt;version&gt;1.0.58&lt;/version&gt;
&lt;/dependency&gt;
</pre>
</p>
......
......@@ -40,7 +40,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3>
<h3>Version 1.0.x (2007-09-x)</h3><ul>
<li>After deleting data, empty space in the database files was not efficiently reused
<li>When using IFNULL, NULLIF, COALESCE, LEAST, or GREATEST,
and the first parameter was ?, an exception was thrown.
Now the higest data type of all parameters is used.
</li><li>When comparing TINYINT or SMALLINT columns against constants, the index was not used. Fixed.
</li><li>Maven 2: new version are now automatically synched with the central repositories.
</li><li>The default value for MAX_MEMORY_UNDO is now 100000.
</li><li>The documentation indexer does no longer index Japanese pages.
If somebody knows how to split Japanese into words please post it.
</li><li>Oracle compatibility: SYSDATE now returns a timestamp. CHR(..) is now an alias for CHAR(..).
</li><li>After deleting data, empty space in the database files was not efficiently reused
(but it was reused when opening the database). This has been fixed.
</li><li>About 230 bytes per database was leaked. This is a problem for applications
opening and closing many thousand databases. The main problem: a shutdown hook
......@@ -744,6 +753,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>Document org.h2.samples.MixedMode
</li><li>Server: use one listener (detect if the request comes from an PG or TCP client)
</li><li>Store dates as 'local'. Existing files use GMT. Use escape syntax for backward compatiblity)
</li><li>Support data type INTERVAL
</li></ul>
<h3>Not Planned</h3>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2849,7 +2849,7 @@ public class Parser {
} else if (s.equals("SYSTIME")) {
return CURRENT_TIME;
} else if (s.equals("SYSDATE")) {
return CURRENT_DATE;
return CURRENT_TIMESTAMP;
}
return getKeywordOrIdentifier(s, "SELECT", KEYWORD);
case 'T':
......
......@@ -48,7 +48,7 @@ public class SysProperties {
public static final int DATASOURCE_TRACE_LEVEL = getIntSetting("h2.dataSourceTraceLevel", TraceSystem.ERROR);
public static final int CACHE_SIZE_DEFAULT = getIntSetting("h2.cacheSizeDefault", 16 * 1024);
public static final int CACHE_SIZE_INDEX_SHIFT = getIntSetting("h2.cacheSizeIndexShift", 3);
public static final int DEFAULT_MAX_MEMORY_UNDO = getIntSetting("h2.defaultMaxMemoryUndo", 50000);
public static final int DEFAULT_MAX_MEMORY_UNDO = getIntSetting("h2.defaultMaxMemoryUndo", 100000);
public static final boolean OPTIMIZE_NOT = getBooleanSetting("h2.optimizeNot", true);
public static final boolean OPTIMIZE_TWO_EQUALS = getBooleanSetting("h2.optimizeTwoEquals", true);
public static final int DEFAULT_LOCK_MODE = getIntSetting("h2.defaultLockMode", Constants.LOCK_MODE_READ_COMMITTED);
......
......@@ -49,6 +49,7 @@ import org.h2.util.CacheLRU;
import org.h2.util.ClassUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.IntHashMap;
import org.h2.util.MemoryFile;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
......@@ -96,7 +97,7 @@ public class Database implements DataHandler {
private FileLock lock;
private LogSystem log;
private WriterThread writer;
private ObjectArray storages = new ObjectArray();
private IntHashMap storageMap = new IntHashMap();
private boolean starting;
private DiskFile fileData, fileIndex;
private TraceSystem traceSystem;
......@@ -568,6 +569,7 @@ public class Database implements DataHandler {
private void removeUnusedStorages(Session session) throws SQLException {
if (persistent) {
ObjectArray storages = getAllStorages();
for (int i = 0; i < storages.size(); i++) {
Storage storage = (Storage) storages.get(i);
if (storage != null && storage.getRecordReader() == null) {
......@@ -595,30 +597,23 @@ public class Database implements DataHandler {
public void removeStorage(int id, DiskFile file) {
if (SysProperties.CHECK) {
Storage s = (Storage) storages.get(id);
Storage s = (Storage) storageMap.get(id);
if (s == null || s.getDiskFile() != file) {
throw Message.getInternalError();
}
}
storages.set(id, null);
storageMap.remove(id);
}
public Storage getStorage(int id, DiskFile file) {
Storage storage = null;
if (storages.size() > id) {
storage = (Storage) storages.get(id);
Storage storage = (Storage) storageMap.get(id);
if (storage != null) {
if (SysProperties.CHECK && storage.getDiskFile() != file) {
throw Message.getInternalError();
}
}
}
if (storage == null) {
} else {
storage = new Storage(this, file, null, id);
while (storages.size() <= id) {
storages.add(null);
}
storages.set(id, storage);
storageMap.put(id, storage);
}
return storage;
}
......@@ -910,7 +905,7 @@ public class Database implements DataHandler {
} catch (SQLException e) {
traceSystem.getTrace(Trace.DATABASE).error("close", e);
}
storages = new ObjectArray();
storageMap.clear();
}
private void checkMetaFree(Session session, int id) throws SQLException {
......@@ -931,7 +926,8 @@ public class Database implements DataHandler {
if ((i & 1) != (dataFile ? 1 : 0)) {
i++;
}
while (i < storages.size() || objectIds.get(i)) {
while (storageMap.get(i) != null || objectIds.get(i)) {
i++;
if ((i & 1) != (dataFile ? 1 : 0)) {
i++;
......@@ -1414,7 +1410,7 @@ public class Database implements DataHandler {
}
public ObjectArray getAllStorages() {
return storages;
return new ObjectArray(storageMap.values());
}
public boolean getRecovery() {
......
......@@ -95,6 +95,11 @@ public class Comparison extends Condition {
dataType = left.getType();
} else {
right = right.optimize(session);
if (left instanceof ExpressionColumn && right.isConstant()) {
right = getCast(right, left.getType(), left.getPrecision(), left.getScale(), session);
} else if (right instanceof ExpressionColumn && left.isConstant()) {
left = getCast(left, right.getType(), right.getPrecision(), right.getScale(), session);
}
int lt = left.getType(), rt = right.getType();
if (lt == rt) {
if (lt == Value.UNKNOWN) {
......
......@@ -185,6 +185,7 @@ public class Function extends Expression implements FunctionCall {
addFunction("ASCII", ASCII, 1, Value.INT);
addFunction("BIT_LENGTH", BIT_LENGTH, 1, Value.INT);
addFunction("CHAR", CHAR, 1, Value.STRING);
addFunction("CHR", CHAR, 1, Value.STRING);
addFunction("CHAR_LENGTH", CHAR_LENGTH, 1, Value.INT);
addFunction("CHARACTER_LENGTH", CHAR_LENGTH, 1, Value.INT); // same as
// CHAR_LENGTH
......@@ -1350,17 +1351,21 @@ public class Function extends Expression implements FunctionCall {
case COALESCE:
case LEAST:
case GREATEST: {
dataType = Value.STRING;
dataType = Value.UNKNOWN;
scale = 0;
precision = 0;
for (int i = 0; i < args.length; i++) {
Expression e = args[i];
if (e != ValueExpression.NULL) {
dataType = e.getType();
scale = e.getScale();
precision = e.getPrecision();
break;
if (e != ValueExpression.NULL && e.getType() != Value.UNKNOWN) {
dataType = Value.getHigherOrder(dataType, e.getType());
scale = Math.max(scale, e.getScale());
precision = Math.max(precision, e.getPrecision());
}
}
if (dataType == Value.UNKNOWN) {
dataType = Value.STRING;
scale = 0;
precision = 0;
}
break;
}
......
......@@ -910,8 +910,7 @@ SET MAX_MEMORY_ROWS 1000
SET MAX_MEMORY_UNDO int
","
The maximum number of undo records per a session that are kept in-memory.
If a transaction is larger, the records are buffered to disk.
The default value is Integer.MAX_VALUE (that means the feature is disabled by default).
If a transaction is larger, the records are buffered to disk. The default value is 100000.
Changes to tables without a primary key can not be buffered to disk.
This setting is persistent.
Admin rights are required to execute this command.
......@@ -2045,7 +2044,7 @@ Each character needs 2 bytes.
OCTET_LENGTH(NAME)
"
"Functions (String)","CHAR","
CHAR(int): string
{CHAR | CHR}(int): string
","
Returns the character that represents the ASCII value.
","
......
package org.h2.util;
import java.util.Collection;
import java.util.HashMap;
public class IntHashMap {
private final HashMap map = new HashMap();
public Object get(int key) {
return map.get(ObjectUtils.getInteger(key));
}
public void put(int key, Object value) {
map.put(ObjectUtils.getInteger(key), value);
}
public void remove(int key) {
map.remove(ObjectUtils.getInteger(key));
}
public int size() {
return map.size();
}
public void clear() {
map.clear();
}
public Collection values() {
return map.values();
}
}
......@@ -28,6 +28,7 @@ public class TestPreparedStatement extends TestBase {
deleteDb("preparedStatement");
Connection conn = getConnection("preparedStatement");
testCoalesce(conn);
testPreparedStatementMetaData(conn);
testDate(conn);
testArray(conn);
......@@ -48,6 +49,16 @@ public class TestPreparedStatement extends TestBase {
conn.close();
}
private void testCoalesce(Connection conn) throws Exception {
Statement stat = conn.createStatement();
stat.executeUpdate("create table test(tm timestamp)");
stat.executeUpdate("insert into test values(current_timestamp)");
PreparedStatement prep = conn.prepareStatement("update test set tm = coalesce(?,tm)");
prep.setTimestamp(1, new java.sql.Timestamp(System.currentTimeMillis()));
prep.executeUpdate();
stat.executeUpdate("drop table test");
}
private void testPreparedStatementMetaData(Connection conn) throws Exception {
PreparedStatement prep = conn.prepareStatement("select * from table(x int = ?, name varchar = ?)");
ResultSetMetaData meta = prep.getMetaData();
......
--- special grammar and test cases ---------------------------------------------------------------------------------------------
create table test(id smallint primary key);
> ok
insert into test values(1), (2), (3);
> update count: 3
explain select * from test where id = 1;
> PLAN
> -------------------------------------------------------------------------------
> SELECT TEST.ID FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_1: ID = 1 */ WHERE ID = 1
> rows: 1
drop table test;
> ok
create table test(id tinyint primary key);
> ok
insert into test values(1), (2), (3);
> update count: 3
explain select * from test where id = 3;
> PLAN
> -------------------------------------------------------------------------------
> SELECT TEST.ID FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_1: ID = 3 */ WHERE ID = 3
> rows: 1
explain select * from test where id = 255;
> exception
drop table test;
> ok
create table test(id int primary key);
> ok
......@@ -313,8 +346,8 @@ select * from test where name = -1 and name = id;
explain select * from test where name = -1 and name = id;
> PLAN
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------
> SELECT TEST.ID, TEST.NAME FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_1: ID = -1 */ WHERE ((CAST(NAME AS INTEGER) = -1) AND (CAST(NAME AS INTEGER) = ID)) AND (-1 = ID)
> ----------------------------------------------------------------------------------------------------------------------------
> SELECT TEST.ID, TEST.NAME FROM PUBLIC.TEST /* PUBLIC.TEST_TABLE_SCAN */ WHERE (NAME = '-1') AND (CAST(NAME AS INTEGER) = ID)
> rows: 1
DROP TABLE TEST;
......
file conversion should be done automatically when the new engine connects.
auto-upgrade application:
check if new version is available
(option: digital signature)
if yes download new version
(option: http, https, ftp)
backup database to SQL script
(option: list of databases, use recovery mechanism)
install new version
ftp client
task to download new version from another HTTP / HTTPS / FTP server
multi-task
DROP TABLE TEST;
CREATE TABLE TEST(ID INT);
INSERT INTO TEST VALUES(1);
INSERT INTO TEST VALUES(2);
SELECT ID AS A FROM TEST WHERE A>0;
-- Yes: HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, MySQL, H2, Derby
SELECT ID AS A FROM TEST ORDER BY A;
-- Yes: Oracle, MS SQL Server, PostgreSQL, MySQL, H2, Derby, HSQLDB
SELECT ID AS A FROM TEST ORDER BY -A;
-- Yes: Oracle, MySQL, HSQLDB
-- Fail: MS SQL Server, PostgreSQL, H2, Derby
SELECT ID AS A FROM TEST GROUP BY A;
-- Yes: PostgreSQL, MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, H2, Derby
SELECT ID AS A FROM TEST GROUP BY -A;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
SELECT ID AS A FROM TEST GROUP BY ID HAVING A>0;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
SELECT COUNT(*) AS A FROM TEST GROUP BY ID HAVING A>0;
-- Yes: MySQL, HSQLDB
-- Fail: Oracle, MS SQL Server, PostgreSQL, H2, Derby
h2
update FOO set a = dateadd('second', 4320000, a);
ms sql server
update FOO set a = dateadd(s, 4320000, a);
mysql
update FOO set a = date_add(a, interval 4320000 second);
postgresql
update FOO set a = a + interval '4320000 s';
oracle
update FOO set a = a + INTERVAL '4320000' SECOND;
......@@ -98,3 +98,33 @@ SELECT * FROM test WHERE family_name IN ('de Smith', 'Smith');
-- OOPS, the comparison's operands are sorted incorrectly for ignorecase!
EXPLAIN SELECT * FROM test WHERE family_name IN ('de Smith', 'Smith');
-------------------
complete recursive views:
drop all objects;
create table parent(id int primary key, parent int);
insert into parent values(1, null), (2, 1), (3, 1);
with test_view(id, parent) as
select id, parent from parent where id = ?
union all
select parent.id, parent.parent from test_view, parent
where parent.parent = test_view.id
select * from test_view {1: 1};
drop view test_view;
with test_view(id, parent) as
select id, parent from parent where id = 1
union all
select parent.id, parent.parent from test_view, parent
where parent.parent = test_view.id
select * from test_view;
drop view test_view;
drop table parent;
......@@ -161,6 +161,9 @@ public class Indexer {
if (!lower.endsWith(".html") && !lower.endsWith(".htm")) {
return;
}
if (lower.indexOf("_ja.") >= 0) {
return;
}
if (!noIndex.contains(fileName)) {
page = new Page(pages.size(), fileName);
pages.add(page);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论