提交 28077cb0 authored 作者: Thomas Mueller's avatar Thomas Mueller

Documentation.

上级 4263bc30
...@@ -226,7 +226,7 @@ to write to a table (update or delete a row), an exclusive lock is required. To ...@@ -226,7 +226,7 @@ to write to a table (update or delete a row), an exclusive lock is required. To
exclusive lock, other connection must not have any locks on the object. After the exclusive lock, other connection must not have any locks on the object. After the
connection commits, all locks are released. connection commits, all locks are released.
This database keeps all locks in memory. This database keeps all locks in memory.
When releasing a lock, one of the waiting connections is picked at random. When a lock is released, and multiple connections are waiting for it, one of them is picked at random.
</p> </p>
<h3>Lock Timeout</h3> <h3>Lock Timeout</h3>
......
...@@ -37,7 +37,7 @@ Change Log ...@@ -37,7 +37,7 @@ Change Log
</li><li>DROP VIEW now supports the CASCADE and RESTRICT clauses (patch from Kerry Sainsbury) </li><li>DROP VIEW now supports the CASCADE and RESTRICT clauses (patch from Kerry Sainsbury)
</li><li>CREATE VIEW now supports the OR REPLACE clause (patch from Kerry Sainsbury) </li><li>CREATE VIEW now supports the OR REPLACE clause (patch from Kerry Sainsbury)
</li><li>Build tool: ability to only run one test using the -Dtest=className setting. </li><li>Build tool: ability to only run one test using the -Dtest=className setting.
eg: build -Dtest=org.h2.test.db.TestViewDropView test (patch from Kerry Sainsbury) eg: build -Dtest=org.h2.test.db.TestViewDropView test (patch from Kerry Sainsbury).
</li></ul> </li></ul>
<h2>Version 1.2.137 (2010-06-06)</h2> <h2>Version 1.2.137 (2010-06-06)</h2>
......
...@@ -353,7 +353,7 @@ encrypted using AES-128 and XTEA encryption algorithms ...@@ -353,7 +353,7 @@ encrypted using AES-128 and XTEA encryption algorithms
*7 Derby only supports updatable result sets if the query is not sorted.<br /> *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.<br /> *8 Derby and HSQLDB don't support standard compliant information schema tables.<br />
*9 When using MVCC (multi version concurrency).<br /> *9 When using MVCC (multi version concurrency).<br />
*10 Derby and HSQLDB *10 Derby and HSQLDB
<a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29">don't hide hide data patterns well</a>.<br /> <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29">don't hide hide data patterns well</a>.<br />
*11 The MULTI_THREADED option is not enabled by default, and not yet supported when using MVCC. *11 The MULTI_THREADED option is not enabled by default, and not yet supported when using MVCC.
</p> </p>
......
...@@ -60,7 +60,8 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -60,7 +60,8 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Deferred integrity checking (DEFERRABLE INITIALLY DEFERRED). </li><li>Deferred integrity checking (DEFERRABLE INITIALLY DEFERRED).
</li><li>Groovy Stored Procedures: http://groovy.codehaus.org/Groovy+SQL </li><li>Groovy Stored Procedures: http://groovy.codehaus.org/Groovy+SQL
</li><li>Add a migration guide (list differences between databases). </li><li>Add a migration guide (list differences between databases).
</li><li>Migrate database tool (also from other database engines). </li><li>Migrate database tool (also from other database engines). For Oracle, maybe use
DBMS_METADATA.GET_DDL / GET_DEPENDENT_DDL.
</li><li>Optimization: automatic index creation suggestion using the trace file? </li><li>Optimization: automatic index creation suggestion using the trace file?
</li><li>Compression performance: don't allocate buffers, compress / expand in to out buffer. </li><li>Compression performance: don't allocate buffers, compress / expand in to out buffer.
</li><li>Rebuild index functionality to shrink index size and improve performance. </li><li>Rebuild index functionality to shrink index size and improve 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.
...@@ -3558,8 +3558,8 @@ public class Parser { ...@@ -3558,8 +3558,8 @@ public class Parser {
private Prepared parseCreate() { private Prepared parseCreate() {
boolean orReplace = false; boolean orReplace = false;
if (readIf("OR")) { if (readIf("OR")) {
read("REPLACE"); read("REPLACE");
orReplace = true; orReplace = true;
} }
boolean force = readIf("FORCE"); boolean force = readIf("FORCE");
......
...@@ -37,6 +37,7 @@ public class RangeTable extends Table { ...@@ -37,6 +37,7 @@ public class RangeTable extends Table {
* @param schema the schema (always the main schema) * @param schema the schema (always the main schema)
* @param min the start expression * @param min the start expression
* @param max the end expression * @param max the end expression
* @param noColumns whether this table has no columns
*/ */
public RangeTable(Schema schema, Expression min, Expression max, boolean noColumns) { public RangeTable(Schema schema, Expression min, Expression max, boolean noColumns) {
super(schema, 0, NAME, true, true); super(schema, 0, NAME, true, true);
......
...@@ -176,7 +176,7 @@ public class TableFilter implements ColumnResolver { ...@@ -176,7 +176,7 @@ public class TableFilter implements ColumnResolver {
if (nestedJoin != null) { if (nestedJoin != null) {
setEvaluatable(nestedJoin); setEvaluatable(nestedJoin);
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, level)); item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, level));
int todoNestJoinCostWrong; int todoCheckCost;
// TODO optimizer: calculate cost of a join: should use separate // TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost // expected row number and lookup cost
item.cost += item.cost * item.getNestedJoinPlan().cost; item.cost += item.cost * item.getNestedJoinPlan().cost;
...@@ -387,6 +387,9 @@ public class TableFilter implements ColumnResolver { ...@@ -387,6 +387,9 @@ public class TableFilter implements ColumnResolver {
return false; return false;
} }
/**
* Set the state of this and all nested tables to the NULL row.
*/
protected void setNullRow() { protected void setNullRow() {
state = NULL_ROW; state = NULL_ROW;
current = table.getNullRow(); current = table.getNullRow();
...@@ -486,6 +489,7 @@ public class TableFilter implements ColumnResolver { ...@@ -486,6 +489,7 @@ public class TableFilter implements ColumnResolver {
* *
* @param filter the joined table filter * @param filter the joined table filter
* @param outer if this is an outer join * @param outer if this is an outer join
* @param nested if this is a nested join
* @param on the join condition * @param on the join condition
*/ */
public void addJoin(TableFilter filter, boolean outer, boolean nested, final Expression on) { public void addJoin(TableFilter filter, boolean outer, boolean nested, final Expression on) {
...@@ -575,7 +579,8 @@ public class TableFilter implements ColumnResolver { ...@@ -575,7 +579,8 @@ public class TableFilter implements ColumnResolver {
} }
/** /**
* Whether this is indirectly an outer joined table (nested within an inner join). * Whether this is indirectly an outer joined table (nested within an inner
* join).
* *
* @return true if it is * @return true if it is
*/ */
...@@ -903,6 +908,11 @@ public class TableFilter implements ColumnResolver { ...@@ -903,6 +908,11 @@ public class TableFilter implements ColumnResolver {
return nestedJoin; return nestedJoin;
} }
/**
* Visit this and all joined or nested table filters.
*
* @param visitor the visitor
*/
public void visit(TableFilterVisitor visitor) { public void visit(TableFilterVisitor visitor) {
TableFilter f = this; TableFilter f = this;
do { do {
...@@ -915,12 +925,21 @@ public class TableFilter implements ColumnResolver { ...@@ -915,12 +925,21 @@ public class TableFilter implements ColumnResolver {
} while (f != null); } while (f != null);
} }
public static interface TableFilterVisitor {
public void accept(TableFilter f);
}
public boolean isEvaluatable() { public boolean isEvaluatable() {
return evaluatable; return evaluatable;
} }
/**
* A visitor for table filters.
*/
public static interface TableFilterVisitor {
/**
* This method is called for each nested or joined table filter.
*
* @param f the filter
*/
public void accept(TableFilter f);
}
} }
...@@ -152,22 +152,8 @@ public class TableView extends Table { ...@@ -152,22 +152,8 @@ public class TableView extends Table {
} }
public String getDropSQL() { public String getDropSQL() {
return getDropSQL(false);
}
/**
* Build a SQL statement to drop this object.
*
* @param cascade if true, then include the CASCADE clause in the DROP VIEW statement
*
* @return the SQL statement
*/
public String getDropSQL(boolean cascade) {
StatementBuilder buff = new StatementBuilder("DROP VIEW IF EXISTS "); StatementBuilder buff = new StatementBuilder("DROP VIEW IF EXISTS ");
buff.append(getSQL()); buff.append(getSQL());
if (cascade) {
buff.append(" CASCADE");
}
return buff.toString(); return buff.toString();
} }
...@@ -176,11 +162,11 @@ public class TableView extends Table { ...@@ -176,11 +162,11 @@ public class TableView extends Table {
} }
/** /**
* Generate "CREATE" SQL for the view * Generate "CREATE" SQL statement for the view.
* *
* @param orReplace if true, then include the OR REPLACE clause in the SQL * @param orReplace if true, then include the OR REPLACE clause
* @param force if true, then include the FORCE clause in the SQL * @param force if true, then include the FORCE clause
* @return the SQL * @return the SQL statement
*/ */
public String getCreateSQL(boolean orReplace, boolean force) { public String getCreateSQL(boolean orReplace, boolean force) {
StatementBuilder buff = new StatementBuilder("CREATE "); StatementBuilder buff = new StatementBuilder("CREATE ");
...@@ -402,20 +388,4 @@ public class TableView extends Table { ...@@ -402,20 +388,4 @@ public class TableView extends Table {
return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC); return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC);
} }
/**
* Indicate if this view makes use of the given schema
*
* @param schema the name to check for
* @return true of the view uses the given schema.
*/
public boolean usesSchema(Schema schema) {
boolean result = false;
for (Table table : tables) {
if (table.getSchema().equals(schema)) {
result = true;
break;
}
}
return result;
}
} }
...@@ -27,7 +27,7 @@ import org.h2.util.ScriptReader; ...@@ -27,7 +27,7 @@ import org.h2.util.ScriptReader;
*/ */
public class TestNestedJoins extends TestBase { public class TestNestedJoins extends TestBase {
ArrayList<Statement> dbs = New.arrayList(); private ArrayList<Statement> dbs = New.arrayList();
/** /**
* Run just this test. * Run just this test.
...@@ -67,7 +67,9 @@ public class TestNestedJoins extends TestBase { ...@@ -67,7 +67,9 @@ public class TestNestedJoins extends TestBase {
// deleteDerby(); // deleteDerby();
// try { // try {
// Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); // Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
// Connection c2 = DriverManager.getConnection("jdbc:derby:" + getBaseDir() + "/derby/test;create=true", "sa", "sa"); // Connection c2 = DriverManager.getConnection(
// "jdbc:derby:" + getBaseDir() +
// "/derby/test;create=true", "sa", "sa");
// dbs.add(c2.createStatement()); // dbs.add(c2.createStatement());
// } catch (Exception e) { // } catch (Exception e) {
// // database not installed - ok // // database not installed - ok
...@@ -333,8 +335,10 @@ public class TestNestedJoins extends TestBase { ...@@ -333,8 +335,10 @@ public class TestNestedJoins extends TestBase {
insert into b values(3); insert into b values(3);
insert into c values(1, 3); insert into c values(1, 3);
insert into c values(4, 5); insert into c values(4, 5);
explain select * from a left outer join (b left outer join c on b.x = c.y) on a.x = c.x; explain select * from a left outer join
select * from a left outer join (b left outer join c on b.x = c.y) on a.x = c.x; (b left outer join c on b.x = c.y) on a.x = c.x;
select * from a left outer join
(b left outer join c on b.x = c.y) on a.x = c.x;
*/ */
stat.execute("create table a(x int)"); stat.execute("create table a(x int)");
stat.execute("create table b(x int)"); stat.execute("create table b(x int)");
......
/* /*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License, * Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0 * Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). * (http://h2database.com/html/license.html).
* Initial Developer: H2 Group * Initial Developer: H2 Group
*/ */
package org.h2.test.db; package org.h2.test.db;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
/** /**
* Test the impact of DROP VIEW statements on dependent views. * Test the impact of DROP VIEW statements on dependent views.
*/ */
public class TestViewDropView extends TestBase { public class TestViewDropView extends TestBase {
private Connection conn; private Connection conn;
private Statement stat; private Statement stat;
/** /**
* Run just this test. * Run just this test.
* *
* @param a ignored * @param a ignored
*/ */
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
public void test() throws Exception { public void test() throws Exception {
deleteDb("alter"); deleteDb("alter");
conn = getConnection("alter"); conn = getConnection("alter");
stat = conn.createStatement(); stat = conn.createStatement();
testDropViewDefaultBehaviour(); testDropViewDefaultBehaviour();
testDropViewRestrict(); testDropViewRestrict();
testDropViewCascade(); testDropViewCascade();
testCreateOrReplaceView(); testCreateOrReplaceView();
testCreateOrReplaceViewWithNowInvalidDependentViews(); testCreateOrReplaceViewWithNowInvalidDependentViews();
testCreateOrReplaceForceViewWithNowInvalidDependentViews(); testCreateOrReplaceForceViewWithNowInvalidDependentViews();
conn.close(); conn.close();
deleteDb("alter"); deleteDb("alter");
} }
private void testDropViewDefaultBehaviour() throws SQLException { private void testDropViewDefaultBehaviour() throws SQLException {
createTestData(); createTestData();
try { try {
// Should fail because have dependencies // Should fail because have dependencies
stat.execute("drop view v1"); stat.execute("drop view v1");
if (SysProperties.DROP_RESTRICT) { if (SysProperties.DROP_RESTRICT) {
fail(); fail();
} }
} catch (SQLException e) { } catch (SQLException e) {
if (!SysProperties.DROP_RESTRICT) { if (!SysProperties.DROP_RESTRICT) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode()); assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
} }
} }
if (SysProperties.DROP_RESTRICT) { if (SysProperties.DROP_RESTRICT) {
checkViewRemainsValid(); checkViewRemainsValid();
} }
} }
private void testDropViewRestrict() throws SQLException { private void testDropViewRestrict() throws SQLException {
createTestData(); createTestData();
try { try {
// Should fail because have dependencies // Should fail because have dependencies
stat.execute("drop view v1 restrict"); stat.execute("drop view v1 restrict");
fail(); fail();
} catch (SQLException e) { } catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode()); assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
} }
checkViewRemainsValid(); checkViewRemainsValid();
} }
private void testDropViewCascade() throws SQLException { private void testDropViewCascade() throws SQLException {
createTestData(); createTestData();
stat.execute("drop view v1 cascade"); stat.execute("drop view v1 cascade");
try { try {
stat.execute("select * from v1"); stat.execute("select * from v1");
fail("Exception should be thrown - v1 should be deleted"); fail("Exception should be thrown - v1 should be deleted");
} catch (SQLException e) { } catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode()); assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
} }
try { try {
stat.execute("select * from v2"); stat.execute("select * from v2");
fail("Exception should be thrown - v2 should be deleted"); fail("Exception should be thrown - v2 should be deleted");
} catch (SQLException e) { } catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode()); assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
} }
try { try {
stat.execute("select * from v3"); stat.execute("select * from v3");
fail("Exception should be thrown - v3 should be deleted"); fail("Exception should be thrown - v3 should be deleted");
} catch (SQLException e) { } catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode()); assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
} }
stat.execute("drop table test"); stat.execute("drop table test");
} }
private void testCreateOrReplaceView() throws SQLException { private void testCreateOrReplaceView() throws SQLException {
createTestData(); createTestData();
stat.execute("create or replace view v1 as select a as b, b as a, c from test"); stat.execute("create or replace view v1 as select a as b, b as a, c from test");
checkViewRemainsValid(); checkViewRemainsValid();
} }
private void testCreateOrReplaceViewWithNowInvalidDependentViews() throws SQLException { private void testCreateOrReplaceViewWithNowInvalidDependentViews() throws SQLException {
createTestData(); createTestData();
try { try {
// v2 and v3 need more than just "c", so we should get an error // v2 and v3 need more than just "c", so we should get an error
stat.execute("create or replace view v1 as select c from test"); stat.execute("create or replace view v1 as select c from test");
fail("Exception should be thrown - dependent views need more columns than just 'c'"); fail("Exception should be thrown - dependent views need more columns than just 'c'");
} catch (SQLException e) { } catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode()); assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
} }
// Make sure our old views come back ok // Make sure our old views come back ok
checkViewRemainsValid(); checkViewRemainsValid();
} }
private void testCreateOrReplaceForceViewWithNowInvalidDependentViews() throws SQLException { private void testCreateOrReplaceForceViewWithNowInvalidDependentViews() throws SQLException {
createTestData(); createTestData();
// v2 and v3 need more than just "c", but we want to force the creation of v1 anyway // v2 and v3 need more than just "c",
stat.execute("create or replace force view v1 as select c from test"); // but we want to force the creation of v1 anyway
stat.execute("create or replace force view v1 as select c from test");
try {
// now v2 and v3 are broken, but they still exist -- if there is any value to that...? try {
ResultSet rs = stat.executeQuery("select b from v2"); // now v2 and v3 are broken, but they still exist
assertTrue(rs.next()); ResultSet rs = stat.executeQuery("select b from v2");
assertEquals(1, rs.getInt(1)); assertTrue(rs.next());
assertFalse(rs.next()); assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
} catch (SQLException e) {
assertEquals(ErrorCode.COLUMN_NOT_FOUND_1, e.getErrorCode()); } catch (SQLException e) {
} assertEquals(ErrorCode.COLUMN_NOT_FOUND_1, e.getErrorCode());
}
stat.execute("drop table test");
} stat.execute("drop table test");
}
private void createTestData() throws SQLException {
stat.execute("drop all objects"); private void createTestData() throws SQLException {
stat.execute("create table test(a int, b int, c int)"); stat.execute("drop all objects");
stat.execute("insert into test(a, b, c) values (1, 2, 3)"); stat.execute("create table test(a int, b int, c int)");
stat.execute("create view v1 as select a as b, b as a from test"); stat.execute("insert into test(a, b, c) values (1, 2, 3)");
// child of v1 stat.execute("create view v1 as select a as b, b as a from test");
stat.execute("create view v2 as select * from v1"); // child of v1
// child of v2 stat.execute("create view v2 as select * from v1");
stat.execute("create view v3 as select * from v2"); // child of v2
} stat.execute("create view v3 as select * from v2");
}
private void checkViewRemainsValid() throws SQLException {
ResultSet rs = stat.executeQuery("select b from v1"); private void checkViewRemainsValid() throws SQLException {
assertTrue(rs.next()); ResultSet rs = stat.executeQuery("select b from v1");
assertEquals(1, rs.getInt(1)); assertTrue(rs.next());
assertFalse(rs.next()); assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from v2");
assertTrue(rs.next()); rs = stat.executeQuery("select b from v2");
assertEquals(1, rs.getInt(1)); assertTrue(rs.next());
assertFalse(rs.next()); assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from test");
assertTrue(rs.next()); rs = stat.executeQuery("select b from test");
assertEquals(2, rs.getInt(1)); assertTrue(rs.next());
assertFalse(rs.next()); assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
stat.execute("drop table test");
stat.execute("drop table test");
ResultSet d = conn.getMetaData().getTables(null, null, null, null);
while (d.next()) { ResultSet d = conn.getMetaData().getTables(null, null, null, null);
if (!d.getString(2).equals("INFORMATION_SCHEMA")) { while (d.next()) {
fail("Should have no tables left in the database, not: " + d.getString(2) + "." + d.getString(3)); if (!d.getString(2).equals("INFORMATION_SCHEMA")) {
} fail("Should have no tables left in the database, not: " + d.getString(2) + "." + d.getString(3));
} }
} }
} }
}
...@@ -647,4 +647,4 @@ recorder grajciar recording slovensky uninitialized arriving lubomir unchanged ...@@ -647,4 +647,4 @@ recorder grajciar recording slovensky uninitialized arriving lubomir unchanged
erik dick calculations lutin cite bom evaluating telegard excel bbs deprecation erik dick calculations lutin cite bom evaluating telegard excel bbs deprecation
importing cumulative fired convenient sums judged anybody vacuum encountered importing cumulative fired convenient sums judged anybody vacuum encountered
corresponds cnf informatique ilm boundaries shao crossed retroweaver usr pico corresponds cnf informatique ilm boundaries shao crossed retroweaver usr pico
pengxiang china timestampadd pengxiang china timestampadd picked
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论