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

--no commit message

--no commit message
上级 d46b2da5
...@@ -16,7 +16,9 @@ Change Log ...@@ -16,7 +16,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Support a comma before closing a list, as in: create table test(id int,) <ul><li>NOT IN(SELECT ...) was incorrect if the subquery returns no rows.
</li><li>CREATE TABLE AS SELECT did not work correctly in the multi-version concurrency mode.
</li><li>Support a comma before closing a list, as in: create table test(id int,)
</li><li>MySQL compatibility: linked tables had lower case column names on some systems. </li><li>MySQL compatibility: linked tables had lower case column names on some systems.
</li><li>DB2 compatibility: the DB2 fetch-first-clause is supported. </li><li>DB2 compatibility: the DB2 fetch-first-clause is supported.
</li><li>Oracle compatibility: old style outer join syntax using (+) did work correctly sometimes. </li><li>Oracle compatibility: old style outer join syntax using (+) did work correctly sometimes.
......
...@@ -311,6 +311,13 @@ http://groups.google.com/group/h2-database/web/roadmap ...@@ -311,6 +311,13 @@ http://groups.google.com/group/h2-database/web/roadmap
<td class="compareY">Yes</td> <td class="compareY">Yes</td>
<td class="compareY">Yes</td> <td class="compareY">Yes</td>
</tr><tr> </tr><tr>
<td>Information Schema</td>
<td class="compareY">Yes</td>
<td class="compareY">No *8</td>
<td class="compareY">No *8</td>
<td class="compareY">Yes</td>
<td class="compareY">Yes</td>
</tr><tr>
<td>Computed Columns</td> <td>Computed Columns</td>
<td class="compareY">Yes</td> <td class="compareY">Yes</td>
<td class="compareN">No</td> <td class="compareN">No</td>
...@@ -347,7 +354,8 @@ http://groups.google.com/group/h2-database/web/roadmap ...@@ -347,7 +354,8 @@ http://groups.google.com/group/h2-database/web/roadmap
*4 Derby only supports global temporary tables.<br /> *4 Derby only supports global temporary tables.<br />
*5 The default H2 jar file contains debug information, jar files for other databases do not.<br /> *5 The default H2 jar file contains debug information, jar files for other databases do not.<br />
*6 PostgreSQL supports functional indexes.<br /> *6 PostgreSQL supports functional indexes.<br />
*7 Derby only supports updatable result sets if the query is not sorted. *7 Derby only supports updatable result sets if the query is not sorted.<br />
*8 Derby and HSQLDB don't support standard compliant information schema tables.
</p> </p>
<h3>Derby and HSQLDB</h3> <h3>Derby and HSQLDB</h3>
......
...@@ -51,6 +51,12 @@ JaQu does not require or contain any data caching mechanism. Like JDBC and iBati ...@@ -51,6 +51,12 @@ JaQu does not require or contain any data caching mechanism. Like JDBC and iBati
JaQu provides full control over when and what SQL statements are executed. JaQu provides full control over when and what SQL statements are executed.
</p> </p>
<h3>Restrictions</h3>
<p>
Primitive types (eg. boolean, int, long, double) are not supported. Instead,
Boolean, Integer, Long, and Double must be used.
</p>
<h3>Why in Java?</h3> <h3>Why in Java?</h3>
<p> <p>
Most people use Java in their application. Mixing Java and another language (for example Scala or Groovy) Most people use Java in their application. Mixing Java and another language (for example Scala or Groovy)
...@@ -211,4 +217,55 @@ public class Test { ...@@ -211,4 +217,55 @@ public class Test {
} }
</pre> </pre>
<h2>Configuration</h2>
<p>
JaQu does not require any kind of configuration is you want to use the default mapping.
To define table indices, or if you want to map a class to a table with a different name,
or a field to a column with another name, create a function called 'define' in the data class.
Example:
</p>
<pre>
public class Product implements Table {
public Integer productId;
public String productName;
public String category;
public Double unitPrice;
public Integer unitsInStock;
public void define() {
tableName("Product");
primaryKey(productId);
index(productName, category);
}
</pre>
<p>
The method 'define()' contains the mapping definition. It is called once
when the class is used for the first time. Like annotations, the mapping is defined in the class itself.
Unlike when using annotations, the compiler can check the syntax even for multi-column
objects (multi-column indexes, multi-column primary keys and so on).
This solution is very flexible because the definition is written in regular Java code:
Unlike when using annotations, your code can select the right configuration depending
on the environment if required.
</p>
<h2>Ideas</h2>
<p>
This project has just been started, and nothing is fixed yet.
Some ideas for what to implement include:
</p>
<ul><li>Provide API level compatibility with JPA (so that JaQu can be used as an extension of JPA).
</li><li>Internally use a JPA implementation (for example Hibernate) instead of SQL directly.
</li><li>Use PreparedStatements and cache them.
</li></ul>
<h2>Related Projects</h2>
<p>
<a href="http://www.jequel.de/">JEQUEL: Java Embedded QUEry Language</a><br />
<a href="http://quaere.codehaus.org/">Quaere</a><br />
<a href="http://svn.quaere.codehaus.org/browse/~raw,r=76/quaere/trunk/Quaere/src/test/java/org/quaere/alias/test/SamplesTest.java">Quaere (Alias implementation)</a><br />
<a href="http://josql.sourceforge.net/">JoSQL</a><br />
<a href="http://groups.google.de/group/jlinq">Google Group about adding LINQ features to Java</a><br />
</p>
</div></td></tr></table><!-- analytics --></body></html> </div></td></tr></table><!-- analytics --></body></html>
...@@ -59,6 +59,7 @@ Of course, patches are always welcome, but are not always applied as is. Patches ...@@ -59,6 +59,7 @@ Of course, patches are always welcome, but are not always applied as is. Patches
</li><li>H2 Console: new option 'Open a browser when starting the H2 Console'. </li><li>H2 Console: new option 'Open a browser when starting the H2 Console'.
</li><li>Better space re-use in the files after deleting data: shrink the data file without closing the database (if the end of the file is empty) </li><li>Better space re-use in the files after deleting data: shrink the data file without closing the database (if the end of the file is empty)
</li><li>Full outer joins </li><li>Full outer joins
</li><li>Support trigger on the tables information_schema.tables and ...columns
</li><li>Test very large databases and LOBs (up to 256 GB) </li><li>Test very large databases and LOBs (up to 256 GB)
</li><li>Support hints for the optimizer (which index to use, enforce the join order). </li><li>Support hints for the optimizer (which index to use, enforce the join order).
</li><li>Change LOB mechanism (less files, keep index of lob files, point to files and row, delete unused files earlier, maybe bundle files into a tar file) </li><li>Change LOB mechanism (less files, keep index of lob files, point to files and row, delete unused files earlier, maybe bundle files into a tar file)
...@@ -188,7 +189,6 @@ Of course, patches are always welcome, but are not always applied as is. Patches ...@@ -188,7 +189,6 @@ Of course, patches are always welcome, but are not always applied as is. Patches
</li><li>Tree join functionality </li><li>Tree join functionality
</li><li>Support alter table add column if table has views defined </li><li>Support alter table add column if table has views defined
</li><li>Add multiple columns at the same time with ALTER TABLE .. ADD .. ADD .. </li><li>Add multiple columns at the same time with ALTER TABLE .. ADD .. ADD ..
</li><li>Support trigger on the tables information_schema.tables and ...columns
</li><li>Add H2 to Gem (Ruby install system) </li><li>Add H2 to Gem (Ruby install system)
</li><li>API for functions / user tables </li><li>API for functions / user tables
</li><li>Order conditions inside AND / OR to optimize the performance </li><li>Order conditions inside AND / OR to optimize the performance
......
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.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -784,6 +784,9 @@ public class Select extends Query { ...@@ -784,6 +784,9 @@ public class Select extends Query {
if (on != null) { if (on != null) {
if (!on.isEverything(ExpressionVisitor.EVALUATABLE)) { if (!on.isEverything(ExpressionVisitor.EVALUATABLE)) {
if (f.isJoinOuter()) { if (f.isJoinOuter()) {
// this will check if all columns exist - it may or may not throw an exception
on = on.optimize(session);
// it is not supported even if the columns exist
throw Message.getSQLException(ErrorCode.UNSUPPORTED_OUTER_JOIN_CONDITION_1, on.getSQL()); throw Message.getSQLException(ErrorCode.UNSUPPORTED_OUTER_JOIN_CONDITION_1, on.getSQL());
} }
f.removeJoinCondition(); f.removeJoinCondition();
......
...@@ -49,7 +49,7 @@ public class Session implements SessionInterface { ...@@ -49,7 +49,7 @@ public class Session implements SessionInterface {
private static int nextSerialId; private static int nextSerialId;
private int serialId = nextSerialId++; private final int serialId = nextSerialId++;
private User user; private User user;
private int id; private int id;
private Database database; private Database database;
...@@ -474,6 +474,9 @@ public class Session implements SessionInterface { ...@@ -474,6 +474,9 @@ public class Session implements SessionInterface {
} }
if (undoLogEnabled) { if (undoLogEnabled) {
undoLog.add(log); undoLog.add(log);
} else {
log.commit();
log.getRow().commit();
} }
} }
......
...@@ -338,8 +338,8 @@ public class TableData extends Table implements RecordReader { ...@@ -338,8 +338,8 @@ public class TableData extends Table implements RecordReader {
return; return;
} }
if (!force && database.isMultiVersion()) { if (!force && database.isMultiVersion()) {
// MVCC: update, delete, and insert use a shared lock // MVCC: update, delete, and insert use a shared lock.
// select doesn't lock // Select doesn't lock
if (exclusive) { if (exclusive) {
exclusive = false; exclusive = false;
} else { } else {
...@@ -379,11 +379,12 @@ public class TableData extends Table implements RecordReader { ...@@ -379,11 +379,12 @@ public class TableData extends Table implements RecordReader {
if (lockExclusive == null) { if (lockExclusive == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED || lockMode == Constants.LOCK_MODE_ROW) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED || lockMode == Constants.LOCK_MODE_ROW) {
if (!database.getMultiThreaded() && !database.isMultiVersion()) { if (!database.getMultiThreaded() && !database.isMultiVersion()) {
// READ_COMMITTED read locks are acquired but they // READ_COMMITTED: a read lock is acquired,
// are released immediately // but released immediately after the operation
// when allowing only one thread, no read locks are // is complete.
// required // When allowing only one thread, no lock is
// row level locks work like read committed // required.
// Row level locks work like read committed.
return; return;
} }
} }
......
...@@ -272,6 +272,19 @@ java org.h2.test.TestAll timer ...@@ -272,6 +272,19 @@ java org.h2.test.TestAll timer
/* /*
drop table test;
create table test(id int);
insert into test values(null);
insert into test values(1);
select * from test where id not in (select id from test where 1=0);
select * from test where null not in (select id from test where 1=0);
select * from test where not (id in (select id from test where 1=0));
select * from test where not (null in (select id from test where 1=0));
HSQLDB, MySQL, H2: empty
PostgreSQL, Derby: 1; null
Support large updates (use the transaction log to undo). Support large updates (use the transaction log to undo).
H2 Console: support single file upload and directory download (optional) H2 Console: support single file upload and directory download (optional)
......
...@@ -18,11 +18,29 @@ import org.h2.test.TestBase; ...@@ -18,11 +18,29 @@ import org.h2.test.TestBase;
public class TestMvcc3 extends TestBase { public class TestMvcc3 extends TestBase {
public void test() throws Exception { public void test() throws Exception {
testCreateTableAsSelect();
testSequence(); testSequence();
testDisableAutoCommit(); testDisableAutoCommit();
testRollback(); testRollback();
} }
private void testCreateTableAsSelect() throws Exception {
if (!config.mvcc) {
return;
}
deleteDb("mvcc3");
Connection c1 = getConnection("mvcc3");
Statement s1 = c1.createStatement();
s1.execute("CREATE TABLE TEST AS SELECT X ID, 'Hello' NAME FROM SYSTEM_RANGE(1, 3)");
Connection c2 = getConnection("mvcc3");
Statement s2 = c2.createStatement();
ResultSet rs = s2.executeQuery("SELECT NAME FROM TEST WHERE ID=1");
rs.next();
assertEquals("Hello", rs.getString(1));
c1.close();
c2.close();
}
private void testRollback() throws Exception { private void testRollback() throws Exception {
if (!config.mvcc) { if (!config.mvcc) {
return; return;
......
...@@ -7,12 +7,11 @@ ...@@ -7,12 +7,11 @@
package org.h2.test.rowlock; package org.h2.test.rowlock;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
/** /**
* Row level locking tests. * Row level locking tests.
...@@ -20,7 +19,7 @@ import org.h2.tools.DeleteDbFiles; ...@@ -20,7 +19,7 @@ import org.h2.tools.DeleteDbFiles;
public class TestRowLocks extends TestBase { public class TestRowLocks extends TestBase {
private Connection c1, c2; private Connection c1, c2;
private Statement s1; private Statement s1, s2;
public void test() throws Exception { public void test() throws Exception {
testSetMode(); testSetMode();
...@@ -28,9 +27,8 @@ public class TestRowLocks extends TestBase { ...@@ -28,9 +27,8 @@ public class TestRowLocks extends TestBase {
} }
private void testSetMode() throws Exception { private void testSetMode() throws Exception {
DeleteDbFiles.execute(null, "test", true); deleteDb("rowLocks");
Class.forName("org.h2.Driver"); c1 = getConnection("rowLocks");
c1 = DriverManager.getConnection("jdbc:h2:test", "sa", "sa");
Statement stat = c1.createStatement(); Statement stat = c1.createStatement();
stat.execute("SET LOCK_MODE 4"); stat.execute("SET LOCK_MODE 4");
ResultSet rs = stat.executeQuery("call lock_mode()"); ResultSet rs = stat.executeQuery("call lock_mode()");
...@@ -41,15 +39,40 @@ public class TestRowLocks extends TestBase { ...@@ -41,15 +39,40 @@ public class TestRowLocks extends TestBase {
private void testCases() throws Exception { private void testCases() throws Exception {
deleteDb("rowLocks"); deleteDb("rowLocks");
c1 = getConnection("rowLocks"); c1 = getConnection("rowLocks;MVCC=TRUE");
s1 = c1.createStatement(); s1 = c1.createStatement();
s1.execute("SET LOCK_MODE 4"); s1.execute("SET LOCK_MODE 4");
c2 = getConnection("rowLocks"); s1.execute("CREATE TABLE TEST AS SELECT X ID, 'Hello' NAME FROM SYSTEM_RANGE(1, 3)");
// s2 = c2.createStatement(); c1.commit();
c1.setAutoCommit(false); c1.setAutoCommit(false);
s1.execute("UPDATE TEST SET NAME='Hallo' WHERE ID=1");
c2 = getConnection("rowLocks");
c2.setAutoCommit(false); c2.setAutoCommit(false);
s2 = c2.createStatement();
ResultSet rs = s1.executeQuery("SELECT NAME FROM TEST WHERE ID=1");
rs.next();
assertEquals("Hallo", rs.getString(1));
rs = s2.executeQuery("SELECT NAME FROM TEST WHERE ID=1");
rs.next();
assertEquals("Hello", rs.getString(1));
s2.execute("UPDATE TEST SET NAME='Hallo' WHERE ID=2");
try {
s2.executeUpdate("UPDATE TEST SET NAME='Hallo2' WHERE ID=1");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
c1.commit();
c2.commit();
rs = s1.executeQuery("SELECT NAME FROM TEST WHERE ID=1");
rs.next();
assertEquals("Hallo", rs.getString(1));
rs = s2.executeQuery("SELECT NAME FROM TEST WHERE ID=1");
rs.next();
assertEquals("Hallo", rs.getString(1));
c1.close(); c1.close();
c2.close(); c2.close();
} }
......
--- special grammar and test cases --------------------------------------------------------------------------------------------- --- special grammar and test cases ---------------------------------------------------------------------------------------------
create table test(id int);
> ok
insert into test values(null), (1);
> update count: 2
select * from test where id not in (select id from test where 1=0);
> ID
> ----
> 1
> null
> rows: 2
select * from test where null not in (select id from test where 1=0);
> ID
> ----
> 1
> null
> rows: 2
select * from test where not (id in (select id from test where 1=0));
> ID
> ----
> 1
> null
> rows: 2
select * from test where not (null in (select id from test where 1=0));
> ID
> ----
> 1
> null
> rows: 2
drop table test;
> ok
create table test(a int); create table test(a int);
> ok > ok
......
...@@ -554,4 +554,4 @@ widows msgbox designer styles families uno soffice orphans stan ucb rem ...@@ -554,4 +554,4 @@ widows msgbox designer styles families uno soffice orphans stan ucb rem
pdfurl upate pagebreak ren echo atlassian buggy submitted xcopy invention pdfurl upate pagebreak ren echo atlassian buggy submitted xcopy invention
harbor generics pojo annotations ecl subclipse jmx bean plugins team cha emma harbor generics pojo annotations ecl subclipse jmx bean plugins team cha emma
nullsoft annotation cover scriptable guidelines consider batis coding nullsoft annotation cover scriptable guidelines consider batis coding
anlytc art orafusion anlytc art orafusion ery ideas jequel indices quaere
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论