提交 774b1795 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 dae44578
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
<!--
Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>H2 データベース エンジン</title>
<script type="text/javascript" src="navigation.js"></script>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<link rel="alternate" type="application/atom+xml" title="H2 Newsfeed" href="http://www.h2database.com/html/newsfeed-atom.xml" />
<link rel="alternate" type="application/rss+xml" title="H2 Newsfeed" href="http://www.h2database.com/html/newsfeed-rss.xml" />
</head>
<frameset cols="180,*" rows="*" frameborder="2" framespacing="4" border="4" onLoad="loadFrameset()">
<frame frameborder="0" marginheight="0" marginwidth="0" src="search_ja.html" name="menu" />
<frame frameborder="0" marginheight="0" marginwidth="0" src="main_ja.html" name="main" />
</frameset>
<noframes>
<body>
<p>
H2 (for 'Hypersonic 2') is free a Java SQL DBMS.
Clustering, embedded and server mode, transactions, referential integrity,
views, subqueries, triggers, encryption, and disk based or in-memory operation
are supported. A browser based console application is included.
If you see this page your browser does not support frames.
Please click here to view the <a href="search_ja.html">index</a>.
</p>
</body>
</noframes>
</html>
...@@ -1125,6 +1125,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1125,6 +1125,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>In MySQL mode, for AUTO_INCREMENT columns, don't set the primary key </li><li>In MySQL mode, for AUTO_INCREMENT columns, don't set the primary key
</li><li>Use JDK 1.4 file locking to create the lock file (but not yet by default); writing a system property to detect concurrent access from the same VM (different classloaders). </li><li>Use JDK 1.4 file locking to create the lock file (but not yet by default); writing a system property to detect concurrent access from the same VM (different classloaders).
</li><li>Read-only sessions (Connection.setReadOnly) </li><li>Read-only sessions (Connection.setReadOnly)
</li><li>Support compatibility for jdbc:hsqldb:res:
</li></ul> </li></ul>
<h3>Not Planned</h3> <h3>Not Planned</h3>
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="ja">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Installation
</title><link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript" src="navigation.js"></script>
</head><body onload="frameMe();">
<table class="content"><tr class="content"><td class="content"><div class="contentDiv">
<h1>インストール</h1>
<a href="#requirements">
必要条件</a><br />
<a href="#supported_platforms">
サポートされているプラットフォーム</a><br />
<a href="#installing">
ソフトウェアのインストール </a><br />
<a href="#directory_structure">
ディレクトリ構成</a><br />
<br /><a name="requirements"></a>
<h2>必要条件</h2>
<p>
データベースを実行するために、以下のソフトウェアが動作することを確認します。 互換性のあるソフトウェアでも動作しますが、テストはされていません。
</p>
<ul>
<li>Windows XP, MacOS, or Linux
</li><li>Recommended Windows file system: NTFS (FAT32 supports files up to 4 GB)
</li><li>Sun JDK 1.4 or newer
</li><li>Mozilla Firefox 1.5 or newer
</li></ul>
<br /><a name="supported_platforms"></a>
<h2>サポートされているプラットフォーム</h2>
<p>
このデータベースはJavaで書かれているため、多くの異なったプラットフォームで実行することができます。 Java 1.4 と 1.5でテストされましたが、GCJを使用することでネイティブコードにコンパイルすることもできます。 ソースコードはJava 1.5の特徴は使われていません。現在、データベースはWindows XPでSun JDKを使用して開発、テストされていますが、 おそらく、他の多くのOSと他のJava Runtime Environmentを使用しても動作するでしょう。
</p>
<br /><a name="installing"></a>
<h2>ソフトウェアのインストール</h2>
<p>
ソフトウェアをインストールするために、インストーラーを実行するか 選択したディレクトリにソフトウェアを解凍します。
</p>
<br /><a name="directory_structure"></a>
<h2>ディレクトリ構成</h2>
<p>
インストール後、下記のディレクトリ構成が作られます:
</p>
<table>
<tr>
<th>ディレクトリ</th>
<th>コンテンツ</th>
</tr>
<tr>
<td>bin</td>
<td>JAR and batch files</td>
</tr>
<tr>
<td>docs</td>
<td>Documentation</td>
</tr>
<tr>
<td>docs/html</td>
<td>HTML pages</td>
</tr>
<tr>
<td>docs/javadoc</td>
<td>Javadoc files</td>
</tr>
<tr>
<td>odbc</td>
<td>ODBC drivers and tools</td>
</tr>
<tr>
<td>service</td>
<td>Tools to run the database as a Windows Service</td>
</tr>
<tr>
<td>src</td>
<td>Source files</td>
</tr>
</table>
</div></td></tr></table></body></html>
差异被折叠。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
H2 Database Engine
</title><link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript" src="navigation.js"></script>
</head><body onload="frameMe();">
<table class="content"><tr class="content"><td class="content"><div class="contentDiv">
<h1>H2 データベース エンジン</h1>
<p>
ようこそ、無料のSQLデータベース、H2へ
</p>
<br />
<p>
<a href="quickstartText_ja.html" style="font-size: 16px; font-weight: bold">クイックスタート</a>
<br />
Click here to get a fast overview.
</p>
<p>
<a href="tutorial_ja.html" style="font-size: 16px; font-weight: bold">チュートリアル</a>
<br />
Go through the samples.
</p>
<p>
<a href="features.html" style="font-size: 16px; font-weight: bold">特徴</a>
<br />
See what this database can do and how to use these features.
</p>
</div></td></tr></table></body></html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="ja">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Quickstart
</title><link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript" src="navigation.js"></script>
</head><body onload="frameMe();">
<table class="content"><tr class="content"><td class="content"><div class="contentDiv">
<h1>クイックスタート</h1>
<a href="#embedding">
Embedding H2 in an Application</a><br />
<a href="#h2_console">
H2 コンソール アプリケーション</a><br />
<br /><a name="embedding"></a>
<h2>Embedding H2 in an Application</h2>
<p>
This database can be used in embedded mode, or in server mode. To use it in embedded mode, you need to:
</p>
<ul>
<li>Add <code>h2.jar</code> to the classpath
</li><li>Use the JDBC driver class: <code>org.h2.Driver</code>
</li><li>The database URL <code>jdbc:h2:~/test</code> opens the database 'test' in your user home directory
</li></ul>
<br /><a name="h2_console"></a>
<h2>H2 コンソール アプリケーション</h2>
<p>
このコンソールはブラウザインターフェースを使ってSQL データベースにアクセスします。
<br />
<img src="images/console.png" alt="Web Browser - H2 Console Server - H2 Database" />
<br />
Windows XPをご使用でなかったり、 期待通りに機能しない場合は、 <a href="tutorial.html">チュートリアル</a> 内の 詳細説明をご覧下さい。
</p>
<h3>手順</h3>
<h4>インストール</h4>
<p>
Windows インストーラーを使用してソフトウェアをインストールしましょう (まだインストールされていない場合)。
</p>
<h4>コンソールを起動する</h4>
<p>
<span class="button">スタート</span>
<span class="button">すべてのプログラム</span>
<span class="button">H2</span>
<span class="button">H2 Console (Command Line)</span>をクリックします:<br />
<img class="screenshot" src="images/quickstart-1.png" alt="screenshot: start H2 Console" /><br />
コンソールウィンドウが 開きます:<br />
<img class="screenshot" src="images/quickstart-2.png" alt="screenshot: H2 Running" /><br />
新しいブラウザで URL http://localhost:8082/ にアクセスして下さい。 ファイアーウォールによるセキュリティ警告を設定することができます。
外部ネットワークから あなたのマシンのデータベースにアクセスされたくないのであれば、ファイアーウォールが他の接続を遮断します。 ローカル接続のみ必要です。
</p>
<h4>ログイン</h4>
<p>
<span class="button">Generic H2</span>を選び、<span class="button">Connect</span>をクリックします:<br />
<img class="screenshot" src="images/quickstart-3.png" alt="screenshot: Login screen" /><br />
ログインされました。
</p>
<h4>サンプル</h4>
<p>
<span class="button">Sample SQL Script</span>をクリックします。: <br />
<img class="screenshot" src="images/quickstart-4.png" alt="screenshot: click on the sample SQL script" /><br />
SQLコマンドがコマンドエリアに表示されます。<br />
</p>
<h4>実行する</h4>
<p>
<span class="button">Run</span>をクリックします:<br />
<img class="screenshot" src="images/quickstart-5.png" alt="screenshot: click Run" /><br />
左側のデータベースアイコンの下に、 新しいテーブル TEST が追加されます。動作とステートメントの結果は、スクリプトの下に表示されます。<br />
<img class="screenshot" src="images/quickstart-6.png" alt="screenshot: see the result" /><br />
</p>
<h4>切断</h4>
<p>
<span class="button">Disconnect</span>をクリックします:<br />
<img src="images/icon_disconnect.gif" alt="Disconnect icon" /><br />
データベースを閉じます。
</p>
<h4>終了</h4>
<p>
コンソールウィンドウを閉じます。詳細は<a href="tutorial.html">チュートリアル</a>をご覧下さい。
</p>
</div></td></tr></table></body></html>
...@@ -44,7 +44,6 @@ Initial Developer: H2 Group ...@@ -44,7 +44,6 @@ Initial Developer: H2 Group
<tr class="search"> <tr class="search">
<td class="search" colspan="2"> <td class="search" colspan="2">
<table id="result" style="border: 0px;"> <table id="result" style="border: 0px;">
<tr><td /></tr>
</table> </table>
</td> </td>
</tr> </tr>
......
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Search</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript" src="search.js"></script>
<script type="text/javascript" src="navigation.js"></script>
</head>
<body style="margin: 10px 0px 0px 0px;" onload="frameMe('menu');">
<div class="menu">
<img border="0" src="images/h2-logo.png" alt="H2 Logo" onclick="document.location='main.html'" />
</div>
<form name="searchForm" action="submit" onsubmit="return goFirst();">
<table width="100%" class="search">
<tr class="search">
<td class="search" colspan="2">
<a href="frame.html" target="_top"><img border="0" src="images/language_en.gif" alt="English" /></a>
<a href="frame_ja.html" target="_top"><img border="0" src="images/language_ja.gif" alt="Japanese" /></a>
</td>
</tr>
<tr class="search">
<td class="search" colspan="2">
<b>検索:</b>
</td>
</tr>
<tr class="search">
<td class="search" colspan="2">
<input id="search" name="search" type="text" size="21" maxlength="100" onKeyup="listWords(this.value, '')" /><br />
<input type="reset" id="clear" style="display:none;" value="Clear" onclick="listWords('', '');" />
</td>
</tr>
<tr class="search" style="display:none;" >
<td width="1%" class="search" style="vertical-align: middle;"><input id="highlight" type="checkbox" checked="checked" onclick="highlightCurrent(this.checked, search.value)" /></td>
<td width="99%" class="search" style="padding: 0px; vertical-align: middle;">Highlight keyword(s)</td>
</tr>
<tr class="search">
<td class="search" colspan="2">
<table id="result" style="border: 0px;">
</table>
</td>
</tr>
</table>
</form>
<div class="menu">
<b><a href="main_ja.html" target="main">ホーム</a></b><br />
<a href="quickstartText_ja.html" target="main">クイックスタート</a><br />
<a href="installation_ja.html" target="main">インストール</a><br />
<a href="tutorial_ja.html" target="main">チュートリアル</a><br />
<a href="features.html" target="main">特徴</a><br />
<a href="performance.html" target="main">パフォーマンス</a><br />
<a href="advanced.html" target="main">Advanced Topics</a><br />
<br />
<b>参照</b><br />
<a href="grammar.html" target="main">SQL文</a><br />
<a href="functions.html" target="main">関数</a><br />
<a href="datatypes.html" target="main">データ型</a><br />
<a href="../javadoc/index.html" target="main">Javadoc JDBC API</a><br />
<a href="../h2.pdf" target="_blank">PDFドキュメント</a><br />
<br />
<b>付録</b><br />
<a href="build.html" target="main">構築</a><br />
<a href="history.html" target="main">歴史とロードマップ</a><br />
<a href="faq.html" target="main">Q&A</a><br />
<a href="license.html" target="main">ライセンス</a><br />
<br />
</div>
</body></html>
差异被折叠。
...@@ -205,7 +205,7 @@ public class ScriptCommand extends ScriptBase { ...@@ -205,7 +205,7 @@ public class ScriptCommand extends ScriptBase {
add(sql, false); add(sql, false);
if(Table.TABLE.equals(tableType)) { if(Table.TABLE.equals(tableType)) {
if(table.canGetRowCount()) { if(table.canGetRowCount()) {
String rowcount = "-- " + table.getRowCount() + " = SELECT COUNT(*) FROM " + table.getSQL(); String rowcount = "-- " + table.getRowCount(session) + " = SELECT COUNT(*) FROM " + table.getSQL();
add(rowcount, false); add(rowcount, false);
} }
if(data) { if(data) {
......
...@@ -735,7 +735,7 @@ public class Database implements DataHandler { ...@@ -735,7 +735,7 @@ public class Database implements DataHandler {
} }
public synchronized Session createSession(User user) { public synchronized Session createSession(User user) {
Session session = new Session(this, user, nextSessionId++); Session session = new Session(this, user, ++nextSessionId);
sessions.add(session); sessions.add(session);
traceSystem.getTrace(Trace.SESSION).info("connecting #" + session.getId() + " to " + databaseName); traceSystem.getTrace(Trace.SESSION).info("connecting #" + session.getId() + " to " + databaseName);
if(delayedCloser != null) { if(delayedCloser != null) {
......
...@@ -155,7 +155,7 @@ public class Aggregate extends Expression { ...@@ -155,7 +155,7 @@ public class Aggregate extends Expression {
switch(type) { switch(type) {
case COUNT_ALL: case COUNT_ALL:
Table table = select.getTopTableFilter().getTable(); Table table = select.getTopTableFilter().getTable();
return ValueLong.get(table.getRowCount()); return ValueLong.get(table.getRowCount(session));
case MIN: case MIN:
case MAX: case MAX:
boolean first = type == MIN; boolean first = type == MIN;
......
...@@ -58,7 +58,7 @@ public class BtreeIndex extends Index implements RecordReader { ...@@ -58,7 +58,7 @@ public class BtreeIndex extends Index implements RecordReader {
if(head != null && head.getConsistent()) { if(head != null && head.getConsistent()) {
setRoot((BtreePage) storage.getRecord(session, head.getRootPosition())); setRoot((BtreePage) storage.getRecord(session, head.getRootPosition()));
needRebuild = false; needRebuild = false;
rowCount = table.getRowCount(); rowCount = table.getRowCount(session);
} else { } else {
truncate(session); truncate(session);
needRebuild = true; needRebuild = true;
...@@ -164,12 +164,17 @@ public class BtreeIndex extends Index implements RecordReader { ...@@ -164,12 +164,17 @@ public class BtreeIndex extends Index implements RecordReader {
public void remove(Session session, Row row) throws SQLException { public void remove(Session session, Row row) throws SQLException {
setChanged(session); setChanged(session);
if(rowCount == 1) { if(SysProperties.MVCC) {
// TODO performance: maybe improve truncate performance in this case
truncate(session);
} else {
root.remove(session, row, 0); root.remove(session, row, 0);
rowCount--; rowCount--;
} else {
if(rowCount == 1) {
// TODO performance: maybe improve truncate performance in this case
truncate(session);
} else {
root.remove(session, row, 0);
rowCount--;
}
} }
} }
...@@ -199,8 +204,8 @@ public class BtreeIndex extends Index implements RecordReader { ...@@ -199,8 +204,8 @@ public class BtreeIndex extends Index implements RecordReader {
} }
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
return 10 * getCostRangeIndex(masks, tableData.getRowCount()); return 10 * getCostRangeIndex(masks, tableData.getRowCount(session));
} }
public Record read(Session session, DataPage s) throws SQLException { public Record read(Session session, DataPage s) throws SQLException {
......
...@@ -30,7 +30,7 @@ public class BtreeLeaf extends BtreePage { ...@@ -30,7 +30,7 @@ public class BtreeLeaf extends BtreePage {
private boolean writePos; private boolean writePos;
private int cachedRealByteCount; private int cachedRealByteCount;
BtreeLeaf(BtreeIndex index, Session session,DataPage s) throws SQLException { BtreeLeaf(BtreeIndex index, Session session, DataPage s) throws SQLException {
super(index); super(index);
writePos = s.readByte() == 'P'; writePos = s.readByte() == 'P';
if(writePos) { if(writePos) {
...@@ -60,7 +60,18 @@ public class BtreeLeaf extends BtreePage { ...@@ -60,7 +60,18 @@ public class BtreeLeaf extends BtreePage {
if (comp == 0) { if (comp == 0) {
if(index.indexType.isUnique()) { if(index.indexType.isUnique()) {
if(!index.isNull(newRow)) { if(!index.isNull(newRow)) {
throw index.getDuplicateKeyException(); if(SysProperties.MVCC) {
int todoMVCC;
// currently, throw a duplicate row exception even if another transaction
// updated or deleted the same row and did not yet commit - PostgreSQL waits but in most cases transactions are committed
if(row.getDeleted() && row.getSessionId() == session.getId()) {
// ignore: deleted
} else {
throw index.getDuplicateKeyException();
}
} else {
throw index.getDuplicateKeyException();
}
} }
} }
comp = index.compareKeys(row, newRow); comp = index.compareKeys(row, newRow);
...@@ -251,7 +262,9 @@ public class BtreeLeaf extends BtreePage { ...@@ -251,7 +262,9 @@ public class BtreeLeaf extends BtreePage {
int size = 2 + dummy.getIntLen() * (len+1); int size = 2 + dummy.getIntLen() * (len+1);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
SearchRow row = (SearchRow) pageData.get(i); SearchRow row = (SearchRow) pageData.get(i);
size += getRowSize(dummy, row); if(!row.getDeleted()) {
size += getRowSize(dummy, row);
}
} }
size += index.getRecordOverhead(); size += index.getRecordOverhead();
cachedRealByteCount = size; cachedRealByteCount = size;
......
...@@ -56,10 +56,12 @@ public class BtreeNode extends BtreePage { ...@@ -56,10 +56,12 @@ public class BtreeNode extends BtreePage {
this.pageData = pageData; this.pageData = pageData;
} }
protected SearchRow getData(Session session, int i) throws SQLException { protected SearchRow getData(int i) throws SQLException {
SearchRow r = (SearchRow) pageData.get(i); SearchRow r = (SearchRow) pageData.get(i);
if(r == null) { if(r == null) {
int p = pageChildren.get(i+1); int p = pageChildren.get(i+1);
// MVCC: get the committed data
Session session = index.getDatabase().getSystemSession();
BtreePage page = index.getPage(session, p); BtreePage page = index.getPage(session, p);
r = page.getFirst(session); r = page.getFirst(session);
pageData.set(i, r); pageData.set(i, r);
......
...@@ -46,7 +46,7 @@ public class FunctionIndex extends Index { ...@@ -46,7 +46,7 @@ public class FunctionIndex extends Index {
return new FunctionCursor(result); return new FunctionCursor(result);
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
if(masks != null) { if(masks != null) {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
......
...@@ -121,7 +121,7 @@ public class HashIndex extends Index { ...@@ -121,7 +121,7 @@ public class HashIndex extends Index {
return new HashCursor(result); return new HashCursor(result);
} }
public long getCost(int[] masks) { public double getCost(Session session, int[] masks) {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
Column column = columns[i]; Column column = columns[i];
int index = column.getColumnId(); int index = column.getColumnId();
......
...@@ -75,7 +75,7 @@ public abstract class Index extends SchemaObject { ...@@ -75,7 +75,7 @@ public abstract class Index extends SchemaObject {
public abstract void add(Session session, Row row) throws SQLException; public abstract void add(Session session, Row row) throws SQLException;
public abstract void remove(Session session, Row row) throws SQLException; public abstract void remove(Session session, Row row) throws SQLException;
public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException; public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException;
public abstract long getCost(int[] masks) throws SQLException; public abstract double getCost(Session session, int[] masks) throws SQLException;
public abstract void remove(Session session) throws SQLException; public abstract void remove(Session session) throws SQLException;
public abstract void truncate(Session session) throws SQLException; public abstract void truncate(Session session) throws SQLException;
public abstract boolean canGetFirstOrLast(boolean first); public abstract boolean canGetFirstOrLast(boolean first);
......
...@@ -59,7 +59,7 @@ public class LinearHashIndex extends Index implements RecordReader { ...@@ -59,7 +59,7 @@ public class LinearHashIndex extends Index implements RecordReader {
firstBucketBlock = 4; firstBucketBlock = 4;
storage = database.getStorage(id, diskFile); storage = database.getStorage(id, diskFile);
storage.setReader(this); storage.setReader(this);
rowCount = table.getRowCount(); rowCount = table.getRowCount(session);
int pos = storage.getNext(null); int pos = storage.getNext(null);
if(pos == -1) { if(pos == -1) {
truncate(session); truncate(session);
...@@ -489,7 +489,7 @@ public class LinearHashIndex extends Index implements RecordReader { ...@@ -489,7 +489,7 @@ public class LinearHashIndex extends Index implements RecordReader {
return new LinearHashCursor(tableData.getRow(session, key)); return new LinearHashCursor(tableData.getRow(session, key));
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
Column column = columns[i]; Column column = columns[i];
int index = column.getColumnId(); int index = column.getColumnId();
......
...@@ -139,7 +139,7 @@ public class LinkedIndex extends Index { ...@@ -139,7 +139,7 @@ public class LinkedIndex extends Index {
} }
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
return 100 + getCostRangeIndex(masks, rowCount + Constants.COST_ROW_OFFSET); return 100 + getCostRangeIndex(masks, rowCount + Constants.COST_ROW_OFFSET);
} }
......
...@@ -48,7 +48,7 @@ public class MetaIndex extends Index { ...@@ -48,7 +48,7 @@ public class MetaIndex extends Index {
return new MetaCursor(rows); return new MetaCursor(rows);
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
if(scan) { if(scan) {
return 10000; return 10000;
} }
......
...@@ -42,7 +42,7 @@ public class RangeIndex extends Index { ...@@ -42,7 +42,7 @@ public class RangeIndex extends Index {
return new RangeCursor(start, end); return new RangeCursor(start, end);
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
return 1; return 1;
} }
......
...@@ -6,6 +6,7 @@ package org.h2.index; ...@@ -6,6 +6,7 @@ package org.h2.index;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
...@@ -42,6 +43,18 @@ public class ScanCursor implements Cursor { ...@@ -42,6 +43,18 @@ public class ScanCursor implements Cursor {
} }
public boolean next() throws SQLException { public boolean next() throws SQLException {
if(SysProperties.MVCC) {
while(true) {
row = scan.getNextRow(session, row);
if(row == null) {
break;
}
if(row.getSessionId() == 0 || row.getSessionId() == session.getId()) {
break;
}
}
return row != null;
}
row = scan.getNextRow(session, row); row = scan.getNextRow(session, row);
return row != null; return row != null;
} }
......
...@@ -142,8 +142,8 @@ public class ScanIndex extends Index { ...@@ -142,8 +142,8 @@ public class ScanIndex extends Index {
return new ScanCursor(session, this); return new ScanCursor(session, this);
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
long cost = tableData.getRowCount() + Constants.COST_ROW_OFFSET; long cost = tableData.getRowCount(session) + Constants.COST_ROW_OFFSET;
if(storage != null) { if(storage != null) {
cost *= 10; cost *= 10;
} }
......
...@@ -293,8 +293,8 @@ public class TreeIndex extends Index { ...@@ -293,8 +293,8 @@ public class TreeIndex extends Index {
} }
} }
public long getCost(int[] masks) throws SQLException { public double getCost(Session session, int[] masks) throws SQLException {
return getCostRangeIndex(masks, tableData.getRowCount()); return getCostRangeIndex(masks, tableData.getRowCount(session));
} }
public void remove(Session session) throws SQLException { public void remove(Session session) throws SQLException {
......
...@@ -212,13 +212,6 @@ public class ViewIndex extends Index { ...@@ -212,13 +212,6 @@ public class ViewIndex extends Index {
return query; return query;
} }
public long getCost(int[] masks) throws SQLException {
if(masks != null) {
throw Message.getUnsupportedException();
}
return Long.MAX_VALUE;
}
public void remove(Session session) throws SQLException { public void remove(Session session) throws SQLException {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
......
...@@ -872,11 +872,11 @@ SET MAX_LENGTH_INPLACE_LOB int ...@@ -872,11 +872,11 @@ SET MAX_LENGTH_INPLACE_LOB int
Sets the maximum size of an in-place LOB object. LOB objects larger Sets the maximum size of an in-place LOB object. LOB objects larger
that this size are stored in a separate file, otherwise stored that this size are stored in a separate file, otherwise stored
directly in the database (in-place). directly in the database (in-place).
The default max size is 128. The default max size is 1024.
This setting is persistent. This setting is persistent.
Admin rights are required to execute this command. Admin rights are required to execute this command.
"," ","
SET MAX_LENGTH_INPLACE_LOB 512 SET MAX_LENGTH_INPLACE_LOB 128
" "
"Commands (Other)","SET MAX_LOG_SIZE"," "Commands (Other)","SET MAX_LOG_SIZE","
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package org.h2.result; package org.h2.result;
import org.h2.engine.Session;
import org.h2.value.Value; import org.h2.value.Value;
public interface SearchRow { public interface SearchRow {
...@@ -13,5 +14,8 @@ public interface SearchRow { ...@@ -13,5 +14,8 @@ public interface SearchRow {
int getColumnCount(); int getColumnCount();
void setValue(int idx, Value v); void setValue(int idx, Value v);
void setPos(int pos); void setPos(int pos);
void setDeleted(Session session, boolean deleted);
int getSessionId();
boolean getDeleted();
} }
...@@ -4,12 +4,15 @@ ...@@ -4,12 +4,15 @@
*/ */
package org.h2.result; package org.h2.result;
import org.h2.engine.Session;
import org.h2.value.Value; import org.h2.value.Value;
public class SimpleRow implements SearchRow { public class SimpleRow implements SearchRow {
private int pos; private int pos;
private Value[] data; private Value[] data;
private int sessionId;
private boolean deleted;
public SimpleRow(Value[] data) { public SimpleRow(Value[] data) {
this.data = data; this.data = data;
...@@ -35,4 +38,18 @@ public class SimpleRow implements SearchRow { ...@@ -35,4 +38,18 @@ public class SimpleRow implements SearchRow {
return data[i]; return data[i];
} }
public boolean getDeleted() {
return deleted;
}
public void setDeleted(Session session, boolean deleted) {
this.sessionId = session.getId();
this.deleted = deleted;
}
public int getSessionId() {
int testing;
return sessionId;
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package org.h2.result; package org.h2.result;
import org.h2.engine.Session;
import org.h2.value.Value; import org.h2.value.Value;
public class SimpleRowValue implements SearchRow { public class SimpleRowValue implements SearchRow {
...@@ -12,6 +13,8 @@ public class SimpleRowValue implements SearchRow { ...@@ -12,6 +13,8 @@ public class SimpleRowValue implements SearchRow {
private int index; private int index;
private int virtualColumnCount; private int virtualColumnCount;
private Value data; private Value data;
private int sessionId;
private boolean deleted;
public SimpleRowValue(int columnCount) { public SimpleRowValue(int columnCount) {
this.virtualColumnCount = columnCount; this.virtualColumnCount = columnCount;
...@@ -35,4 +38,18 @@ public class SimpleRowValue implements SearchRow { ...@@ -35,4 +38,18 @@ public class SimpleRowValue implements SearchRow {
data = v; data = v;
} }
public boolean getDeleted() {
return deleted;
}
public void setDeleted(Session session, boolean deleted) {
this.sessionId = session.getId();
this.deleted = deleted;
}
public int getSessionId() {
int testing;
return sessionId;
}
} }
...@@ -10,6 +10,7 @@ import org.h2.engine.Constants; ...@@ -10,6 +10,7 @@ import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.RandomUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -110,9 +111,11 @@ public class SortOrder { ...@@ -110,9 +111,11 @@ public class SortOrder {
} }
private void sort(ObjectArray rows, int l, int r) throws SQLException { private void sort(ObjectArray rows, int l, int r) throws SQLException {
// quicksort
int i, j; int i, j;
while (r - l > 10) { while (r - l > 10) {
i = (r + l) >> 1; // randomized pivot to avoid worst case
i = RandomUtils.nextInt(r - l - 4) + l + 2;
if (compare((Value[]) rows.get(l), (Value[]) rows.get(r)) > 0) { if (compare((Value[]) rows.get(l), (Value[]) rows.get(r)) > 0) {
swap(rows, l, r); swap(rows, l, r);
} }
......
...@@ -6,6 +6,7 @@ package org.h2.store; ...@@ -6,6 +6,7 @@ package org.h2.store;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.util.CacheObject; import org.h2.util.CacheObject;
...@@ -81,6 +82,12 @@ public abstract class Record extends CacheObject { ...@@ -81,6 +82,12 @@ public abstract class Record extends CacheObject {
if((isChanged() && !isLogWritten()) || isPinned()) { if((isChanged() && !isLogWritten()) || isPinned()) {
return false; return false;
} }
if(SysProperties.MVCC) {
// TODO not required if we write the log only when committed
if(sessionId != 0) {
return false;
}
}
return true; return true;
} }
......
...@@ -113,7 +113,7 @@ public class FunctionTable extends Table { ...@@ -113,7 +113,7 @@ public class FunctionTable extends Table {
return false; return false;
} }
public long getRowCount() throws SQLException { public long getRowCount(Session session) throws SQLException {
throw Message.getInternalError(); throw Message.getInternalError();
} }
......
...@@ -1272,7 +1272,7 @@ public class MetaTable extends Table { ...@@ -1272,7 +1272,7 @@ public class MetaTable extends Table {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
public long getRowCount() { public long getRowCount(Session session) {
throw Message.getInternalError(); throw Message.getInternalError();
} }
......
...@@ -84,7 +84,7 @@ public class RangeTable extends Table { ...@@ -84,7 +84,7 @@ public class RangeTable extends Table {
return false; return false;
} }
public long getRowCount() throws SQLException { public long getRowCount(Session session) throws SQLException {
return max - min; return max - min;
} }
......
...@@ -252,11 +252,11 @@ public abstract class Table extends SchemaObject { ...@@ -252,11 +252,11 @@ public abstract class Table extends SchemaObject {
public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException { public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException {
PlanItem item = new PlanItem(); PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session)); item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(null); item.cost = item.getIndex().getCost(session, null);
ObjectArray indexes = getIndexes(); ObjectArray indexes = getIndexes();
for (int i = 1; indexes != null && masks != null && i < indexes.size(); i++) { for (int i = 1; indexes != null && masks != null && i < indexes.size(); i++) {
Index index = (Index) indexes.get(i); Index index = (Index) indexes.get(i);
long cost = index.getCost(masks); double cost = index.getCost(session, masks);
if (cost < item.cost) { if (cost < item.cost) {
item.cost = cost; item.cost = cost;
item.setIndex(index); item.setIndex(index);
...@@ -440,7 +440,7 @@ public abstract class Table extends SchemaObject { ...@@ -440,7 +440,7 @@ public abstract class Table extends SchemaObject {
public abstract boolean canGetRowCount(); public abstract boolean canGetRowCount();
public abstract boolean canDrop(); public abstract boolean canDrop();
public abstract long getRowCount() throws SQLException; public abstract long getRowCount(Session session) throws SQLException;
public boolean getGlobalTemporary() { public boolean getGlobalTemporary() {
return false; return false;
......
...@@ -243,7 +243,7 @@ public class TableData extends Table implements RecordReader { ...@@ -243,7 +243,7 @@ public class TableData extends Table implements RecordReader {
return true; return true;
} }
public long getRowCount() { public long getRowCount(Session session) {
return rowCount; return rowCount;
} }
......
...@@ -96,7 +96,7 @@ public class TableFilter implements ColumnResolver { ...@@ -96,7 +96,7 @@ public class TableFilter implements ColumnResolver {
if (indexConditions.size() == 0) { if (indexConditions.size() == 0) {
item = new PlanItem(); item = new PlanItem();
item.setIndex(table.getScanIndex(session)); item.setIndex(table.getScanIndex(session));
item.cost = item.getIndex().getCost(null); item.cost = item.getIndex().getCost(session, null);
} else { } else {
int len = table.getColumns().length; int len = table.getColumns().length;
int[] masks = new int[len]; int[] masks = new int[len];
......
...@@ -242,7 +242,7 @@ public class TableLink extends Table { ...@@ -242,7 +242,7 @@ public class TableLink extends Table {
} }
} }
public long getRowCount() throws SQLException { public long getRowCount(Session session) throws SQLException {
PreparedStatement prep = getPreparedStatement("SELECT COUNT(*) FROM "+originalTable); PreparedStatement prep = getPreparedStatement("SELECT COUNT(*) FROM "+originalTable);
ResultSet rs = prep.executeQuery(); ResultSet rs = prep.executeQuery();
rs.next(); rs.next();
......
...@@ -175,7 +175,7 @@ public class TableView extends Table { ...@@ -175,7 +175,7 @@ public class TableView extends Table {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
public long getRowCount() { public long getRowCount(Session session) {
throw Message.getInternalError(); throw Message.getInternalError();
} }
......
...@@ -17,4 +17,8 @@ public class CacheHead extends CacheObject { ...@@ -17,4 +17,8 @@ public class CacheHead extends CacheObject {
public void write(DataPage buff) throws SQLException { public void write(DataPage buff) throws SQLException {
} }
public boolean canRemove() {
return false;
}
} }
...@@ -58,9 +58,7 @@ public abstract class CacheObject { ...@@ -58,9 +58,7 @@ public abstract class CacheObject {
return false; return false;
} }
public boolean canRemove() { abstract public boolean canRemove();
return true;
}
/* /*
* Get the estimated memory size. * Get the estimated memory size.
......
package org.h2.samples;
import java.io.*;
import java.sql.*;
import org.h2.tools.RunScript;
public class InitDatabaseFromJar {
public static void main(String[] args) throws Exception {
new InitDatabaseFromJar().createScript();
new InitDatabaseFromJar().initDb();
}
private void createScript() throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:test");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(NAME VARCHAR)");
stat.execute("INSERT INTO TEST VALUES('Hello World')");
stat.execute("SCRIPT TO 'script.sql'");
conn.close();
}
void initDb() throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:test");
InputStream in = getClass().getResourceAsStream("script.sql");
if(in == null) {
System.out.println("Please add the file script.sql to the classpath, package " + getClass().getPackage().getName());
} else {
RunScript.execute(conn, new InputStreamReader(in));
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM TEST");
while(rs.next()) {
System.out.println(rs.getString(1));
}
conn.close();
}
}
}
...@@ -94,6 +94,16 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -94,6 +94,16 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
/* /*
table with constraint
alter the table
add data
-> object is closed
CREATE TABLE TEST(ID INT, PARENT INT, CONSTRAINT A FOREIGN KEY(PARENT) REFERENCES(ID));
ALTER TABLE TEST ALTER COLUMN PARENT BIGINT;
INSERT INTO TEST VALUES(1, 1, 1);
add MVCC add MVCC
test and document fulltext search test and document fulltext search
......
package org.h2.test.mvcc;
import java.sql.*;
import org.h2.tools.DeleteDbFiles;
public class TestMVCC {
Connection c1, c2;
Statement s1, s2;
public static void main(String[] args) throws Exception {
TestMVCC app = new TestMVCC();
app.test();
}
void test() throws Exception {
// TODO Prio 1: don't store records before they are committed (otherwise re-reading from a different session may return the wrong value)
// TODO Prio 1: getRowCount: different row count for different sessions: TableData
// TODO Prio 2: getRowCount: different row count for different sessions: TableLink (use different connections?)
System.setProperty("h2.mvcc", "true");
DeleteDbFiles.execute(null, "test", true);
Class.forName("org.h2.Driver");
c1 = DriverManager.getConnection("jdbc:h2:test");
s1 = c1.createStatement();
c2 = DriverManager.getConnection("jdbc:h2:test");
s2 = c2.createStatement();
c1.setAutoCommit(false);
c2.setAutoCommit(false);
s1.execute("CREATE TABLE TEST(ID INT, NAME VARCHAR)");
// s1.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
s1.execute("INSERT INTO TEST VALUES(1, 'Hello')");
test(s2, "SELECT COUNT(*) FROM TEST WHERE NAME!='X'", "0");
c1.commit();
// TODO support snapshot isolation
// test(s2, "SELECT COUNT(*) FROM TEST WHERE NAME!='X'", "0");
test(s2, "SELECT COUNT(*) FROM TEST WHERE NAME!='X'", "1");
c1.close();
c2.close();
}
private void test(Statement stat, String sql, String expected) throws Exception {
ResultSet rs = stat.executeQuery(sql);
if(rs.next()) {
String s = rs.getString(1);
if(expected == null) {
throw new Error("expected: no rows, got: " + s);
} else if(!expected.equals(s)) {
throw new Error("expected: " + expected + ", got: " + s);
}
} else {
if(expected != null) {
throw new Error("expected: " + expected + ", got: no rows");
}
}
// TODO Auto-generated method stub
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论