提交 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
exclusive lock, other connection must not have any locks on the object. After the
connection commits, all locks are released.
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>
<h3>Lock Timeout</h3>
......
......@@ -37,7 +37,7 @@ Change Log
</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>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>
<h2>Version 1.2.137 (2010-06-06)</h2>
......
......@@ -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 />
*8 Derby and HSQLDB don't support standard compliant information schema tables.<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 />
*11 The MULTI_THREADED option is not enabled by default, and not yet supported when using MVCC.
</p>
......
......@@ -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>Groovy Stored Procedures: http://groovy.codehaus.org/Groovy+SQL
</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>Compression performance: don't allocate buffers, compress / expand in to out buffer.
</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 {
private Prepared parseCreate() {
boolean orReplace = false;
if (readIf("OR")) {
read("REPLACE");
orReplace = true;
read("REPLACE");
orReplace = true;
}
boolean force = readIf("FORCE");
......
......@@ -37,6 +37,7 @@ public class RangeTable extends Table {
* @param schema the schema (always the main schema)
* @param min the start expression
* @param max the end expression
* @param noColumns whether this table has no columns
*/
public RangeTable(Schema schema, Expression min, Expression max, boolean noColumns) {
super(schema, 0, NAME, true, true);
......
......@@ -176,7 +176,7 @@ public class TableFilter implements ColumnResolver {
if (nestedJoin != null) {
setEvaluatable(nestedJoin);
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, level));
int todoNestJoinCostWrong;
int todoCheckCost;
// TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost
item.cost += item.cost * item.getNestedJoinPlan().cost;
......@@ -387,6 +387,9 @@ public class TableFilter implements ColumnResolver {
return false;
}
/**
* Set the state of this and all nested tables to the NULL row.
*/
protected void setNullRow() {
state = NULL_ROW;
current = table.getNullRow();
......@@ -486,6 +489,7 @@ public class TableFilter implements ColumnResolver {
*
* @param filter the joined table filter
* @param outer if this is an outer join
* @param nested if this is a nested join
* @param on the join condition
*/
public void addJoin(TableFilter filter, boolean outer, boolean nested, final Expression on) {
......@@ -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
*/
......@@ -903,6 +908,11 @@ public class TableFilter implements ColumnResolver {
return nestedJoin;
}
/**
* Visit this and all joined or nested table filters.
*
* @param visitor the visitor
*/
public void visit(TableFilterVisitor visitor) {
TableFilter f = this;
do {
......@@ -915,12 +925,21 @@ public class TableFilter implements ColumnResolver {
} while (f != null);
}
public static interface TableFilterVisitor {
public void accept(TableFilter f);
}
public boolean isEvaluatable() {
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 {
}
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 ");
buff.append(getSQL());
if (cascade) {
buff.append(" CASCADE");
}
return buff.toString();
}
......@@ -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 force if true, then include the FORCE clause in the SQL
* @return the SQL
* @param orReplace if true, then include the OR REPLACE clause
* @param force if true, then include the FORCE clause
* @return the SQL statement
*/
public String getCreateSQL(boolean orReplace, boolean force) {
StatementBuilder buff = new StatementBuilder("CREATE ");
......@@ -402,20 +388,4 @@ public class TableView extends Table {
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;
*/
public class TestNestedJoins extends TestBase {
ArrayList<Statement> dbs = New.arrayList();
private ArrayList<Statement> dbs = New.arrayList();
/**
* Run just this test.
......@@ -67,7 +67,9 @@ public class TestNestedJoins extends TestBase {
// deleteDerby();
// try {
// 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());
// } catch (Exception e) {
// // database not installed - ok
......@@ -333,8 +335,10 @@ public class TestNestedJoins extends TestBase {
insert into b values(3);
insert into c values(1, 3);
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;
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
(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 b(x int)");
......
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Test the impact of DROP VIEW statements on dependent views.
*/
public class TestViewDropView extends TestBase {
private Connection conn;
private Statement stat;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
deleteDb("alter");
conn = getConnection("alter");
stat = conn.createStatement();
testDropViewDefaultBehaviour();
testDropViewRestrict();
testDropViewCascade();
testCreateOrReplaceView();
testCreateOrReplaceViewWithNowInvalidDependentViews();
testCreateOrReplaceForceViewWithNowInvalidDependentViews();
conn.close();
deleteDb("alter");
}
private void testDropViewDefaultBehaviour() throws SQLException {
createTestData();
try {
// Should fail because have dependencies
stat.execute("drop view v1");
if (SysProperties.DROP_RESTRICT) {
fail();
}
} catch (SQLException e) {
if (!SysProperties.DROP_RESTRICT) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
}
if (SysProperties.DROP_RESTRICT) {
checkViewRemainsValid();
}
}
private void testDropViewRestrict() throws SQLException {
createTestData();
try {
// Should fail because have dependencies
stat.execute("drop view v1 restrict");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
checkViewRemainsValid();
}
private void testDropViewCascade() throws SQLException {
createTestData();
stat.execute("drop view v1 cascade");
try {
stat.execute("select * from v1");
fail("Exception should be thrown - v1 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
try {
stat.execute("select * from v2");
fail("Exception should be thrown - v2 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
try {
stat.execute("select * from v3");
fail("Exception should be thrown - v3 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
stat.execute("drop table test");
}
private void testCreateOrReplaceView() throws SQLException {
createTestData();
stat.execute("create or replace view v1 as select a as b, b as a, c from test");
checkViewRemainsValid();
}
private void testCreateOrReplaceViewWithNowInvalidDependentViews() throws SQLException {
createTestData();
try {
// 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");
fail("Exception should be thrown - dependent views need more columns than just 'c'");
} catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
// Make sure our old views come back ok
checkViewRemainsValid();
}
private void testCreateOrReplaceForceViewWithNowInvalidDependentViews() throws SQLException {
createTestData();
// v2 and v3 need more than just "c", 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...?
ResultSet rs = stat.executeQuery("select b from v2");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
} catch (SQLException e) {
assertEquals(ErrorCode.COLUMN_NOT_FOUND_1, e.getErrorCode());
}
stat.execute("drop table test");
}
private void createTestData() throws SQLException {
stat.execute("drop all objects");
stat.execute("create table test(a int, b int, c int)");
stat.execute("insert into test(a, b, c) values (1, 2, 3)");
stat.execute("create view v1 as select a as b, b as a from test");
// child of v1
stat.execute("create view v2 as select * from v1");
// 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");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from v2");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from test");
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
stat.execute("drop table test");
ResultSet d = conn.getMetaData().getTables(null, null, null, null);
while (d.next()) {
if (!d.getString(2).equals("INFORMATION_SCHEMA")) {
fail("Should have no tables left in the database, not: " + d.getString(2) + "." + d.getString(3));
}
}
}
}
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Test the impact of DROP VIEW statements on dependent views.
*/
public class TestViewDropView extends TestBase {
private Connection conn;
private Statement stat;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
deleteDb("alter");
conn = getConnection("alter");
stat = conn.createStatement();
testDropViewDefaultBehaviour();
testDropViewRestrict();
testDropViewCascade();
testCreateOrReplaceView();
testCreateOrReplaceViewWithNowInvalidDependentViews();
testCreateOrReplaceForceViewWithNowInvalidDependentViews();
conn.close();
deleteDb("alter");
}
private void testDropViewDefaultBehaviour() throws SQLException {
createTestData();
try {
// Should fail because have dependencies
stat.execute("drop view v1");
if (SysProperties.DROP_RESTRICT) {
fail();
}
} catch (SQLException e) {
if (!SysProperties.DROP_RESTRICT) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
}
if (SysProperties.DROP_RESTRICT) {
checkViewRemainsValid();
}
}
private void testDropViewRestrict() throws SQLException {
createTestData();
try {
// Should fail because have dependencies
stat.execute("drop view v1 restrict");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
checkViewRemainsValid();
}
private void testDropViewCascade() throws SQLException {
createTestData();
stat.execute("drop view v1 cascade");
try {
stat.execute("select * from v1");
fail("Exception should be thrown - v1 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
try {
stat.execute("select * from v2");
fail("Exception should be thrown - v2 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
try {
stat.execute("select * from v3");
fail("Exception should be thrown - v3 should be deleted");
} catch (SQLException e) {
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e.getErrorCode());
}
stat.execute("drop table test");
}
private void testCreateOrReplaceView() throws SQLException {
createTestData();
stat.execute("create or replace view v1 as select a as b, b as a, c from test");
checkViewRemainsValid();
}
private void testCreateOrReplaceViewWithNowInvalidDependentViews() throws SQLException {
createTestData();
try {
// 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");
fail("Exception should be thrown - dependent views need more columns than just 'c'");
} catch (SQLException e) {
assertEquals(ErrorCode.CANNOT_DROP_2, e.getErrorCode());
}
// Make sure our old views come back ok
checkViewRemainsValid();
}
private void testCreateOrReplaceForceViewWithNowInvalidDependentViews() throws SQLException {
createTestData();
// v2 and v3 need more than just "c",
// 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
ResultSet rs = stat.executeQuery("select b from v2");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
} catch (SQLException e) {
assertEquals(ErrorCode.COLUMN_NOT_FOUND_1, e.getErrorCode());
}
stat.execute("drop table test");
}
private void createTestData() throws SQLException {
stat.execute("drop all objects");
stat.execute("create table test(a int, b int, c int)");
stat.execute("insert into test(a, b, c) values (1, 2, 3)");
stat.execute("create view v1 as select a as b, b as a from test");
// child of v1
stat.execute("create view v2 as select * from v1");
// 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");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from v2");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
rs = stat.executeQuery("select b from test");
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
stat.execute("drop table test");
ResultSet d = conn.getMetaData().getTables(null, null, null, null);
while (d.next()) {
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
erik dick calculations lutin cite bom evaluating telegard excel bbs deprecation
importing cumulative fired convenient sums judged anybody vacuum encountered
corresponds cnf informatique ilm boundaries shao crossed retroweaver usr pico
pengxiang china timestampadd
pengxiang china timestampadd picked
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论