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

--no commit message

--no commit message
上级 c9dd1fe3
......@@ -17,6 +17,8 @@ History
Change Log</a><br>
<a href="#roadmap">
Roadmap</a><br>
<a href="#supporters">
Supporters</a><br>
<br><a name="history"></a>
<h2>History of this Database Engine</h2>
......@@ -34,6 +36,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3>
<h3>Version 1.0 / TODO</h3><ul>
<li>The command "drop all objects delete files" did not work on linux if the database name was lower case.
<li>When setting the URL to an empty string the DataSource now throws an better exception.
<li>Parsing of LIKE .. ESCAPE did not stop at the expected point. Fixed.
<li>Can now use UUID columns as generated key values. However, the UUID column must be the primary key.
<li>Improved the Javadoc documentation. Now unsupported features are marked with [Not supported],
and partially supported features are [Partially supported].
<li>The forum subscriptions (the emails sent from the forum) now works.
</ul>
<h3>Version 1.0 / 2007-01-17</h3><ul>
<li>Setting the collation (SET COLLATOR) was very slow on some systems (up to 24 seconds).
Thanks a lot to Martina Nissler for finding this problem!
......@@ -1227,6 +1239,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Enable and document optimizations, LOB files in directories
<li>Special methods for DataPage.writeByte / writeShort and so on
<li>Index organized tables CREATE TABLE...(...) ORGANIZATION INDEX (store in data file) (probably file format changes are required for rowId)
<li>Change the default for NULL || 'x' to NULL
<li>Change the default isolation level to read committed
</ul>
<h3>Priority 1</h3>
......@@ -1491,6 +1505,11 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Delay reading the row if data is not required
<li>Eliminate undo log records if stored on disk (just one pointer per block, not per record)
<li>User defined aggregate functions
<li>System property for base directory (h2.baseDir) in embedded mode
<li>Feature matrix like here: http://www.inetsoftware.de/products/jdbc/mssql/features/default.asp.
<li>Updatable resultset on table without primary key or unique index
<li>Use LinkedList instead of ArrayList where applicable
<li>Optimization: (A=B AND B=C) > (A=B AND B=C AND A=C)
</ul>
<h3>Not Planned</h3>
......@@ -1499,4 +1518,15 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>String.intern (so that Strings can be compared with ==) will not be used because some VMs have problems when used extensively
</ul>
<br><a name="supporters"></a>
<h2>Supporters</h2>
Many thanks for those who helped by finding and reporting bugs, gave valuable feedback,
spread the word and have translated this project. Also many thanks to the donors who contributed
via PayPal:
<ul>
<li>Florent Ramiere, France
<li>Pete Haidinyak, USA
<li>Jun Iyama, USA
</ul>
</div></td></tr></table></body></html>
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<?
$spam2 = ("false" == $spam) ? "" : "SPAM";
$now = date('Y-m-d H:i:s');
$body = "Email: $email
Message:
$text
";
$headers = 'From: newsletter@h2database.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail("dbsupport@h2database.com", "[H2 Newsletter] $now $spam2", $body, $headers);
?>
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><title>
H2 Database
</title><link rel="stylesheet" type="text/css" href="../stylesheet.css"></head><body>
<table class="content"><tr class="content"><td class="content"><div class="contentDiv">
<h2>The email was sent successfully</h2>
You have subscribed to the H2 newsletter.
Your email addresses will only be used in this context.
</div></td></tr></table></body></html>
\ No newline at end of file
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<?
$spam2 = ("false" == $spam) ? "" : "SPAM";
$now = date('Y-m-d H:i:s');
$body = "Email: $email
Message:
$text
";
$headers = 'From: feedback@h2database.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$headers =
mail("dbsupport@h2database.com", "[H2 Feedback] $now $spam2", $body, $headers);
?>
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><title>
H2 Database
</title><link rel="stylesheet" type="text/css" href="../stylesheet.css"></head><body>
<table class="content"><tr class="content"><td class="content"><div class="contentDiv">
<h2>The email was sent successfully</h2>
Thank you for your feedback!
</div></td></tr></table></body></html>
\ No newline at end of file
......@@ -15,7 +15,7 @@ import java.util.EventListener;
public interface DatabaseEventListener extends EventListener {
int STATE_SCAN_FILE = 0, STATE_CREATE_INDEX = 1, STATE_RECOVER = 2;
int STATE_SCAN_FILE = 0, STATE_CREATE_INDEX = 1, STATE_RECOVER = 2, STATE_BACKUP_FILE = 3;
/**
* This method is called just after creating the object.
......@@ -35,7 +35,7 @@ public interface DatabaseEventListener extends EventListener {
void diskSpaceIsLow(long stillAvailable) throws SQLException;
/**
* This method is called if an exception occured.
* This method is called if an exception occurred.
*
* @param e the exception
*/
......
......@@ -124,7 +124,7 @@ public class Bnf {
addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL);
addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END);
addFixedRule("anything", RuleFixed.ANY_WORD);
addFixedRule("@hexStart@", RuleFixed.HEXSTART);
addFixedRule("@hexStart@", RuleFixed.HEX_START);
addFixedRule("@concat@", RuleFixed.CONCAT);
addFixedRule("@az_@", RuleFixed.AZ_);
addFixedRule("@af@", RuleFixed.AF);
......@@ -215,7 +215,7 @@ public class Bnf {
if(firstChar != '}') {
throw new Error("expected }, got " + currentToken+ " syntax:" + syntax);
}
} else if("@commadots@".equals(currentToken)) {
} else if("@commaDots@".equals(currentToken)) {
r = new RuleList(new RuleElement(",", currentTopic), lastRepeat, false);
r = new RuleRepeat(r);
} else if("@dots@".equals(currentToken)) {
......@@ -245,7 +245,7 @@ public class Bnf {
syntax = StringUtils.replaceAll(syntax, "nnnnnnnnn", "@nanos@");
syntax = StringUtils.replaceAll(syntax, "function", "@func@");
syntax = StringUtils.replaceAll(syntax, "0x", "@hexStart@");
syntax = StringUtils.replaceAll(syntax, ",...", "@commadots@");
syntax = StringUtils.replaceAll(syntax, ",...", "@commaDots@");
syntax = StringUtils.replaceAll(syntax, "...", "@dots@");
syntax = StringUtils.replaceAll(syntax, "||", "@concat@");
syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@");
......
......@@ -16,7 +16,7 @@ public class RuleFixed implements Rule {
public static final int ANY_UNTIL_EOL = 5;
public static final int ANY_UNTIL_END = 6;
public static final int ANY_WORD = 7;
public static final int HEXSTART = 10, CONCAT = 11, AZ_ = 12, AF = 13, DIGIT = 14;
public static final int HEX_START = 10, CONCAT = 11, AZ_ = 12, AF = 13, DIGIT = 14;
private int type;
......@@ -45,7 +45,7 @@ public class RuleFixed implements Rule {
}
return buff.toString();
}
case HEXSTART:
case HEX_START:
return "0x";
case CONCAT:
return "||";
......@@ -134,7 +134,7 @@ public class RuleFixed implements Rule {
}
}
break;
case HEXSTART:
case HEX_START:
if(StringUtils.toUpperEnglish(s).startsWith("0X")) {
s = s.substring(2);
} else if(StringUtils.toUpperEnglish(s).startsWith("0")) {
......@@ -209,7 +209,7 @@ public class RuleFixed implements Rule {
break;
case ANY_WORD:
break;
case HEXSTART:
case HEX_START:
if(query.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD);
} else if(query.equals("0")) {
......
......@@ -89,7 +89,7 @@ public class CommandRemote implements CommandInterface {
if(session.isClustered() || scrollable) {
readRows = Integer.MAX_VALUE;
} else {
readRows = Constants.SERVER_SMALL_RESULTSET_SIZE;
readRows = Constants.SERVER_SMALL_RESULT_SET_SIZE;
}
transfer.writeInt(readRows);
sendParameters(transfer);
......@@ -173,7 +173,7 @@ public class CommandRemote implements CommandInterface {
session.traceOperation("COMMAND_CLOSE", id);
transfer.writeInt(SessionRemote.COMMAND_CLOSE).writeInt(id);
} catch (IOException e) {
// TODO cluster: do we need to to handle ioexception on close?
// TODO cluster: do we need to to handle io exception on close?
trace.error("close", e);
}
}
......@@ -182,7 +182,7 @@ public class CommandRemote implements CommandInterface {
}
// public void finalize() {
// if(!Database.RUN_FINALIZERS) {
// if(!Constants.RUN_FINALIZE) {
// return;
// }
// close();
......
......@@ -124,7 +124,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
checkNoViews();
if(table.getColumns().length == 1) {
// TODO test each sql exception
throw Message.getSQLException(Message.CANT_DROP_LAST_COLUMN, oldColumn.getSQL());
throw Message.getSQLException(Message.CANNOT_DROP_LAST_COLUMN, oldColumn.getSQL());
}
table.checkColumnIsNotReferenced(oldColumn);
dropSingleColumnIndexes();
......
......@@ -56,7 +56,7 @@ public class DropTable extends SchemaCommand {
} else {
session.getUser().checkRight(table, Right.ALL);
if(!table.canDrop()) {
throw Message.getSQLException(Message.CANT_DROP_TABLE_1, tableName);
throw Message.getSQLException(Message.CANNOT_DROP_TABLE_1, tableName);
}
table.lock(session, true);
}
......
......@@ -39,7 +39,7 @@ public class DropUser extends DefineCommand {
}
} else {
if(user == session.getUser()) {
throw Message.getSQLException(Message.CANT_DROP_CURRENT_USER);
throw Message.getSQLException(Message.CANNOT_DROP_CURRENT_USER);
}
db.removeDatabaseObject(session, user);
}
......
......@@ -28,7 +28,7 @@ public class TruncateTable extends SchemaCommand {
session.commit();
Table table = getSchema().getTableOrView(session, tableName);
if(!table.canTruncate()) {
throw Message.getSQLException(Message.CANT_TRUNCATE_1, tableName);
throw Message.getSQLException(Message.CANNOT_TRUNCATE_1, tableName);
} else {
session.getUser().checkRight(table, Right.DELETE);
table.lock(session, true);
......
......@@ -91,24 +91,24 @@ public class Optimizer {
}
private void calculateBruteForceAll() throws SQLException {
TableFilter[] ftry = new TableFilter[filters.length];
Permutations perm = new Permutations(filters, ftry);
for(int x=0; !canStop(x) && perm.next(); x++) {
testPlan(ftry);
TableFilter[] list = new TableFilter[filters.length];
Permutations p = new Permutations(filters, list);
for(int x=0; !canStop(x) && p.next(); x++) {
testPlan(list);
}
}
private void calculateBruteForceSome() throws SQLException {
int bruteForce = getMaxBruteForceFilters(filters.length);
TableFilter[] ftry = new TableFilter[filters.length];
Permutations perm = new Permutations(filters, ftry, bruteForce);
for(int x=0; !canStop(x) && perm.next(); x++) {
TableFilter[] list = new TableFilter[filters.length];
Permutations p = new Permutations(filters, list, bruteForce);
for(int x=0; !canStop(x) && p.next(); x++) {
// find out what filters are not used yet
for(int i=0; i<filters.length; i++) {
filters[i].setUsed(false);
}
for(int i=0; i<bruteForce; i++) {
ftry[i].setUsed(true);
list[i].setUsed(true);
}
// fill the remaining elements with the unused elements (greedy)
for(int i=bruteForce; i<filters.length; i++) {
......@@ -120,8 +120,8 @@ public class Optimizer {
bestPart = j;
break;
}
ftry[i] = filters[j];
Plan part = new Plan(ftry, i+1, condition);
list[i] = filters[j];
Plan part = new Plan(list, i+1, condition);
double costNow = part.calculateCost(session);
if (costPart < 0 || costNow < costPart) {
costPart = costNow;
......@@ -130,41 +130,41 @@ public class Optimizer {
}
}
filters[bestPart].setUsed(true);
ftry[i] = filters[bestPart];
list[i] = filters[bestPart];
}
testPlan(ftry);
testPlan(list);
}
}
private void calculateGenetic() throws SQLException {
TableFilter[] fbest = new TableFilter[filters.length];
TableFilter[] ftry = new TableFilter[filters.length];
TableFilter[] best = new TableFilter[filters.length];
TableFilter[] list = new TableFilter[filters.length];
for(int x=0; x<MAX_GENETIC; x++) {
if(canStop(x)) {
break;
}
boolean generateRandom = (x & 127) == 0;
if(!generateRandom) {
System.arraycopy(fbest, 0, ftry, 0, filters.length);
if(!shuffleTwo(ftry)) {
System.arraycopy(best, 0, list, 0, filters.length);
if(!shuffleTwo(list)) {
generateRandom = true;
}
}
if(generateRandom) {
switched = new BitSet();
System.arraycopy(filters, 0, fbest, 0, filters.length);
shuffleAll(fbest);
System.arraycopy(fbest, 0, ftry, 0, filters.length);
System.arraycopy(filters, 0, best, 0, filters.length);
shuffleAll(best);
System.arraycopy(best, 0, list, 0, filters.length);
}
if(testPlan(ftry)) {
if(testPlan(list)) {
switched = new BitSet();
System.arraycopy(ftry, 0, fbest, 0, filters.length);
System.arraycopy(list, 0, best, 0, filters.length);
}
}
}
private boolean testPlan(TableFilter[] ftry) throws SQLException {
Plan p = new Plan(ftry, ftry.length, condition);
private boolean testPlan(TableFilter[] list) throws SQLException {
Plan p = new Plan(list, list.length, condition);
double costNow = p.calculateCost(session);
if (cost < 0 || costNow < cost) {
cost = costNow;
......
......@@ -109,9 +109,9 @@ public abstract class Query extends Prepared {
boolean isAlias = false;
idx = expressions.size();
if(e instanceof ExpressionColumn) {
ExpressionColumn ecol = (ExpressionColumn)e;
String alias = ecol.getOriginalAliasName();
String col = ecol.getOriginalColumnName();
ExpressionColumn exprCol = (ExpressionColumn)e;
String alias = exprCol.getOriginalAliasName();
String col = exprCol.getOriginalColumnName();
for(int j=0; j<visible; j++) {
boolean found = false;
Expression ec = (Expression) expressions.get(j);
......
......@@ -316,7 +316,7 @@ public class Select extends Query {
}
topTableFilter.startQuery();
topTableFilter.reset();
// TODO lock tables of subqueries
// TODO lock tables of sub queries
topTableFilter.lock(session, isForUpdate);
if(isQuickQuery) {
queryQuick(columnCount, result);
......@@ -557,10 +557,10 @@ public class Select extends Query {
int id=0;
do {
if(id > 0) {
buff.append('\n');
buff.append("\n");
}
id++;
buff.append(filter.getPlanSQL(join));
id++;
join = true;
filter = filter.getJoin();
} while(filter != null);
......@@ -570,16 +570,16 @@ public class Select extends Query {
if(groupIndex != null) {
buff.append("\nGROUP BY ");
for(int i=0; i<groupIndex.length; i++) {
Expression gro = exprList[groupIndex[i]];
Expression g = exprList[groupIndex[i]];
if(i>0) {
buff.append(", ");
}
buff.append(StringUtils.unEnclose(gro.getSQL()));
buff.append(StringUtils.unEnclose(g.getSQL()));
}
}
if(havingIndex >= 0) {
Expression hav = exprList[havingIndex];
buff.append("\nHAVING " + StringUtils.unEnclose(hav.getSQL()));
Expression h = exprList[havingIndex];
buff.append("\nHAVING " + StringUtils.unEnclose(h.getSQL()));
}
if(sort != null) {
buff.append("\nORDER BY ");
......
......@@ -8,7 +8,7 @@ import java.sql.SQLException;
import java.text.Collator;
import org.h2.command.Prepared;
import org.h2.compress.Compresser;
import org.h2.compress.Compressor;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
......@@ -220,7 +220,7 @@ public class Set extends Prepared {
case SetTypes.COMPRESS_LOB: {
session.getUser().checkAdmin();
int algo = CompressTool.getInstance().getCompressAlgorithm(stringValue);
database.setLobCompressionAlgorithm(algo == Compresser.NO ? null : stringValue);
database.setLobCompressionAlgorithm(algo == Compressor.NO ? null : stringValue);
addOrUpdateSetting(name, stringValue, 0);
break;
}
......
......@@ -6,6 +6,7 @@ package org.h2.command.dml;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
......@@ -117,12 +118,6 @@ public class TransactionCommand extends Prepared {
session.close();
break;
}
// case BACKUP: {
// session.getUser().checkAdmin();
// session.commit();
// backupTo("backup.zip");
// break;
// }
default:
throw Message.getInternalError("type=" + type);
}
......@@ -130,15 +125,29 @@ public class TransactionCommand extends Prepared {
}
private void backupTo(String fileName) throws SQLException {
// int todoAddSpecialSQLStatement;
// FileOutputStream fileout = new FileOutputStream("test.zip");
// ZipOutputStream out = new ZipOutputStream(fileout);
// out.putNextEntry(new ZipEntry("test.data.db"));
// DiskFile file = session.getDatabase().getDataFile();
// session.getDatabase().getLog().incStopDeleteFiles(true);
// TODO Auto-generated method stub
// session.getDatabase().getLog().setStopDeleteFiles(false);
//
int todoMoveToOwnCommand;
try {
FileOutputStream fileOut = new FileOutputStream("test.zip");
ZipOutputStream out = new ZipOutputStream(fileOut);
out.putNextEntry(new ZipEntry("test.data.db"));
DiskFile file = session.getDatabase().getDataFile();
try {
session.getDatabase().getLog().updateKeepFiles(1);
int pos = -1;
while(true) {
pos = file.readDirect(pos, out);
if(pos < 0) {
break;
}
}
out.close();
fileOut.close();
} finally {
session.getDatabase().getLog().updateKeepFiles(-1);
}
} catch(IOException e) {
throw Message.convert(e);
}
}
public boolean isTransactional() {
......
......@@ -9,7 +9,7 @@ import java.util.zip.*;
import org.h2.message.Message;
public class CompressDeflate implements Compresser {
public class CompressDeflate implements Compressor {
private int level = Deflater.BEST_SPEED;
private int strategy = Deflater.DEFAULT_STRATEGY;
......@@ -43,7 +43,7 @@ public class CompressDeflate implements Compresser {
}
public int getAlgorithm() {
return Compresser.DEFLATE;
return Compressor.DEFLATE;
}
public void expand(byte[] in, int inPos, int inLen, byte[] out, int outPos, int outLen) throws DataFormatException {
......
......@@ -3,8 +3,8 @@
* Copyright (c) 2000-2005 Marc Alexander Lehmann <schmorp@schmorp.de>
* Copyright (c) 2005 Oren J. Maurice <oymaurice@hazorea.org.il>
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
......@@ -16,15 +16,15 @@
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
......@@ -40,13 +40,13 @@
package org.h2.compress;
public class CompressLZF implements Compresser {
public class CompressLZF implements Compressor {
public void setOptions(String options) {
}
public int getAlgorithm() {
return Compresser.LZF;
return Compressor.LZF;
}
static final int HLOG = 14;
......@@ -177,5 +177,3 @@ public class CompressLZF implements Compresser {
} while (outPos < outLen);
}
}
......@@ -4,10 +4,10 @@
*/
package org.h2.compress;
public class CompressNo implements Compresser {
public class CompressNo implements Compressor {
public int getAlgorithm() {
return Compresser.NO;
return Compressor.NO;
}
public void setOptions(String options) {
......
......@@ -6,7 +6,7 @@ package org.h2.compress;
import java.sql.SQLException;
public interface Compresser {
public interface Compressor {
int NO = 0, LZF = 1, DEFLATE = 2;
......
......@@ -499,8 +499,8 @@ public class ConstraintReferential extends Constraint {
return refTable;
}
public boolean usesIndex(Index ind) {
return ind == index || ind == refIndex;
public boolean usesIndex(Index idx) {
return idx == index || idx == refIndex;
}
public boolean containsColumn(Column col) {
......
......@@ -113,8 +113,8 @@ public class ConstraintUnique extends Constraint {
// unique index check is enough
}
public boolean usesIndex(Index ind) {
return ind == index;
public boolean usesIndex(Index idx) {
return idx == index;
}
public boolean containsColumn(Column col) {
......
......@@ -59,6 +59,9 @@ public class ConnectionInfo {
public ConnectionInfo(String u, Properties info) throws SQLException {
this.originalURL = u;
if(!u.startsWith(Constants.START_URL)) {
throw Message.getInvalidValueException(u, "url");
}
this.url = u;
readProperties(info);
readSettings();
......
......@@ -32,7 +32,7 @@ package org.h2.engine;
* - Check version, change build number in Constants.java and build.xml
* - Check code coverage
* - No " Message.getInternalError" (must be "throw Message.getInternalError")
* - ' #ifdef', ' #endif'
* - space#ifdef', space#endif
* - No TODO in the docs
* - Run regression test with JDK 1.4 and 1.5
* - Change version(s) in performance.html; use latest versions of other databases
......@@ -160,7 +160,7 @@ public class Constants {
public static final String TEMP_TABLE_PREFIX = "TEMP_TABLE_";
public static final String TEMP_TABLE_TRANSACTION_PREFIX = "TEMP_TRANS_TABLE_";
public static final int BIGDECIMAL_SCALE_MAX = 100000;
public static final int BIG_DECIMAL_SCALE_MAX = 100000;
public static final String SCHEMA_MAIN = "PUBLIC";
public static final String SCHEMA_INFORMATION = "INFORMATION_SCHEMA";
......@@ -199,7 +199,7 @@ public class Constants {
public static final int DEFAULT_ALLOW_LITERALS = ALLOW_LITERALS_ALL;
public static final boolean AUTO_CONVERT_LOB_TO_FILES = true;
public static final boolean ALLOW_EMTPY_BTREE_PAGES = true;
public static final boolean ALLOW_EMPTY_BTREE_PAGES = true;
public static final String CONN_URL_INTERNAL = "jdbc:default:connection";
public static final String CONN_URL_COLUMNLIST = "jdbc:columnlist:connection";
......@@ -229,7 +229,7 @@ public class Constants {
public static final int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256);
public static boolean MULTI_THREADED_KERNEL = getBooleanSetting("h2.multiThreadedKernel", false);
public static boolean RUN_FINALIZERS = getBooleanSetting("h2.runFinalizers", true);
public static boolean RUN_FINALIZE = getBooleanSetting("h2.runFinalize", true);
public static final boolean OPTIMIZE_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true);
public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true);
......@@ -240,7 +240,7 @@ public class Constants {
public static final boolean LOG_ALL_ERRORS = getBooleanSetting("h2.logAllErrors", false);
public static final String LOG_ALL_ERRORS_FILE = getStringSetting("h2.logAllErrorsFile", "h2errors.txt");
public static final int SERVER_CACHED_OBJECTS = getIntSetting("h2.serverCachedObjects", 64);
public static final int SERVER_SMALL_RESULTSET_SIZE = getIntSetting("h2.serverSmallResultSetSize", 100);
public static final int SERVER_SMALL_RESULT_SET_SIZE = getIntSetting("h2.serverSmallResultSetSize", 100);
public static final int EMERGENCY_SPACE_INITIAL = getIntSetting("h2.emergencySpaceInitial", 1 * 1024 * 1024);
public static final int EMERGENCY_SPACE_MIN = getIntSetting("h2.emergencySpaceMin", 128 * 1024);
public static final boolean OBJECT_CACHE = getBooleanSetting("h2.objectCache", true);
......
......@@ -498,7 +498,7 @@ public class Database implements DataHandler {
starting = true;
Cursor cursor = metaIdIndex.find(systemSession, null, null);
// first, create all function aliases and sequences because
// they might be used in create table / view / constrants and so on
// they might be used in create table / view / constraints and so on
ObjectArray records = new ObjectArray();
while (cursor.next()) {
MetaRecord rec = new MetaRecord(cursor.get());
......@@ -813,9 +813,10 @@ public class Database implements DataHandler {
Engine.getInstance().close(databaseName);
if(deleteFilesOnDisconnect && persistent) {
deleteFilesOnDisconnect = false;
String directory = FileUtils.getParent(databaseName);
try {
DeleteDbFiles.execute(directory, databaseShortName, true);
String directory = FileUtils.getParent(databaseName);
String name = FileUtils.getFileName(databaseName);
DeleteDbFiles.execute(directory, name, true);
} catch(Exception e) {
// ignore (the trace is closed already)
}
......@@ -1123,7 +1124,7 @@ public class Database implements DataHandler {
String invalid = getFirstInvalidTable();
if(invalid != null) {
obj.getSchema().add(obj);
throw Message.getSQLException(Message.CANT_DROP_2, new String[]{obj.getSQL(), invalid}, null);
throw Message.getSQLException(Message.CANNOT_DROP_2, new String[]{obj.getSQL(), invalid}, null);
}
int id = obj.getId();
obj.removeChildrenAndResources(session);
......
......@@ -29,6 +29,7 @@ import org.h2.table.Table;
import org.h2.table.TableData;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
import org.h2.value.ValueLong;
/**
* @author Thomas
......@@ -46,7 +47,7 @@ public class Session implements SessionInterface {
private Random random;
private LogSystem logSystem;
private int lockTimeout;
private long lastIdentity;
private Value lastIdentity = ValueLong.get(0);
private int firstUncommittedLog = LogSystem.LOG_WRITTEN;
private int firstUncommittedPos = LogSystem.LOG_WRITTEN;
private HashMap savepoints;
......@@ -104,7 +105,7 @@ public class Session implements SessionInterface {
}
protected void finalize() {
if(!Constants.RUN_FINALIZERS) {
if(!Constants.RUN_FINALIZE) {
return;
}
if(database != null) {
......@@ -328,11 +329,11 @@ public class Session implements SessionInterface {
return database.getTrace(traceModuleName);
}
public void setLastIdentity(long last) {
public void setLastIdentity(Value last) {
this.lastIdentity = last;
}
public long getLastIdentity() {
public Value getLastIdentity() {
return lastIdentity;
}
......
......@@ -37,7 +37,7 @@ import org.h2.value.ValueString;
public class Aggregate extends Expression {
// TODO aggregates: make them 'pluggable'
// TODO incomatibility to hsqldb: aggregates: hsqldb uses automatic data type for sum if value is too big,
// TODO incompatibility to hsqldb: aggregates: hsqldb uses automatic data type for sum if value is too big,
// h2 uses the same type as the data
public static final int COUNT_ALL = 0, COUNT = 1, SUM = 2, MIN = 3, MAX = 4, AVG = 5;
public static final int GROUP_CONCAT = 6, STDDEV_POP = 7, STDDEV_SAMP = 8;
......
......@@ -149,7 +149,7 @@ public class CompareLike extends Condition {
if(maxMatch == patternLength) {
filter.addIndexCondition(new IndexCondition(Comparison.EQUAL, l, ValueExpression.get(ValueString.get(begin))));
} else {
// TODO check if this is correct according to Unicode rules (codepoints)
// TODO check if this is correct according to Unicode rules (code points)
String end;
if(begin.length()>0) {
filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(ValueString.get(begin))));
......@@ -189,21 +189,21 @@ public class CompareLike extends Condition {
}
private boolean compare(String s, int pi, int si) {
// TODO check if this is correct according to Unicode rules (codepoints)
// TODO check if this is correct according to Unicode rules (code points)
return compareMode.compareString(patternString.substring(pi, pi+1), s.substring(si, si+1), ignoreCase) == 0;
}
private boolean compareAt(String s, int pi, int si, int slen) {
private boolean compareAt(String s, int pi, int si, int sLen) {
for (; pi < patternLength; pi++) {
int type = types[pi];
switch (type) {
case MATCH:
if ((si >= slen) || !compare(s, pi, si++)) {
if ((si >= sLen) || !compare(s, pi, si++)) {
return false;
}
break;
case ONE:
if (si++ >= slen) {
if (si++ >= sLen) {
return false;
}
break;
......@@ -211,8 +211,8 @@ public class CompareLike extends Condition {
if (++pi >= patternLength) {
return true;
}
while (si < slen) {
if (compare(s, pi, si) && compareAt(s, pi, si, slen)) {
while (si < sLen) {
if (compare(s, pi, si) && compareAt(s, pi, si, sLen)) {
return true;
}
si++;
......@@ -222,7 +222,7 @@ public class CompareLike extends Condition {
throw Message.getInternalError("type="+type);
}
}
return si==slen;
return si==sLen;
}
public boolean test(String pattern, String value, char escape) throws SQLException {
......@@ -246,11 +246,11 @@ public class CompareLike extends Condition {
int type;
if (escape == c) {
if (i >= len - 1) {
throw Message.getSQLException(Message.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterix(p, i));
throw Message.getSQLException(Message.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterisk(p, i));
}
c = p.charAt(++i);
if(c != '_' && c != '%' && c != escape) {
throw Message.getSQLException(Message.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterix(p, i));
throw Message.getSQLException(Message.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterisk(p, i));
}
type = MATCH;
} else if (c == '%') {
......
......@@ -37,7 +37,7 @@ public class ConditionNot extends Condition {
}
public Expression optimize(Session session) throws SQLException {
// TODO optimization: some cases are maybe possible to optimize futher: (NOT ID >= 5)
// TODO optimization: some cases are maybe possible to optimize further: (NOT ID >= 5)
Expression expr = condition.optimize(session);
if(expr.isConstant()) {
Value v = expr.getValue(session);
......
......@@ -213,7 +213,7 @@ public class ExpressionColumn extends Expression {
case ExpressionVisitor.INDEPENDENT:
return this.queryLevel < visitor.queryLevel;
case ExpressionVisitor.EVALUATABLE:
// if the current value is known (evalutable set)
// if the current value is known (evaluatable set)
// or if this columns belongs to a 'higher level' query and is therefore just a parameter
return evaluatable || visitor.queryLevel < this.queryLevel;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
......
......@@ -271,7 +271,7 @@ public class Function extends Expression implements FunctionCall {
addFunctionNotConst("CURRVAL", CURRVAL, VARARGS, Value.LONG);
addFunction("ARRAY_GET", ARRAY_GET, 2, Value.NULL);
addFunction("CSVREAD", CSVREAD, VARARGS, Value.RESULT_SET, false, false);
addFunction("CSVWRITE", CSVWRITE, VARARGS, Value.RESULT_SET, false, false);
addFunction("CSVWRITE", CSVWRITE, VARARGS, Value.NULL, false, false);
addFunctionNotConst("MEMORY_FREE", MEMORY_FREE, 0, Value.INT);
addFunctionNotConst("MEMORY_USED", MEMORY_USED, 0, Value.INT);
addFunctionNotConst("LOCK_MODE", LOCK_MODE, 0, Value.INT);
......@@ -408,6 +408,7 @@ public class Function extends Expression implements FunctionCall {
}
Value v1 = args.length < 2 || args[1] == null ? null : args[1].getValue(session);
Value v2 = args.length < 3 || args[2] == null ? null : args[2].getValue(session);
Value v3 = args.length < 4 || args[3] == null ? null : args[3].getValue(session);
switch (info.type) {
case ABS:
return v0.getSignum() > 0 ? v0 : v0.negate();
......@@ -548,7 +549,6 @@ public class Function extends Expression implements FunctionCall {
if (v1 == ValueNull.INSTANCE || v2 == ValueNull.INSTANCE) {
return v1;
}
Value v3 = args[3].getValue(session);
return ValueString.get(insert(v0.getString(), v1.getInt(), v2.getInt(), v3.getString()));
}
case LOWER:
......@@ -686,7 +686,6 @@ public class Function extends Expression implements FunctionCall {
return ValueNull.INSTANCE;
}
String locale = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString();
Value v3 = args.length <= 3 ? null : args[3].getValue(session);
String tz = v3 == null ? null : v3 == ValueNull.INSTANCE ? null : v3.getString();
return ValueString.get(StringUtils.formatDateTime(v0.getTimestamp(), v1.getString(), locale, tz));
}
......@@ -695,7 +694,6 @@ public class Function extends Expression implements FunctionCall {
return ValueNull.INSTANCE;
}
String locale = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString();
Value v3 = args.length <= 3 ? null : args[3].getValue(session);
String tz = v3 == null ? null : v3 == ValueNull.INSTANCE ? null : v3.getString();
java.util.Date d = StringUtils.parseDateTime(v0.getString(), v1.getString(), locale, tz);
return ValueTimestamp.getNoCopy(new Timestamp(d.getTime()));
......@@ -707,7 +705,7 @@ public class Function extends Expression implements FunctionCall {
case CURRENT_USER:
return ValueString.get(session.getUser().getName());
case IDENTITY:
return ValueLong.get(session.getLastIdentity());
return session.getLastIdentity();
case AUTOCOMMIT:
return ValueBoolean.get(session.getAutoCommit());
case READONLY:
......@@ -740,15 +738,27 @@ public class Function extends Expression implements FunctionCall {
case CSVREAD: {
String fileName = v0.getString();
String columnList = v1 == null ? null : v1.getString();
String[] columns = StringUtils.arraySplit(columnList, ',', true);
String charset = v2 == null ? null : v2.getString();
ValueResultSet vr = ValueResultSet.get(Csv.getInstance().read(fileName, columns, charset));
String fieldSeparatorRead = v3 == null ? null : v3.getString();
Csv csv = Csv.getInstance();
char fieldSeparator = ',';
if(fieldSeparatorRead != null && fieldSeparatorRead.length() > 0) {
fieldSeparator = fieldSeparatorRead.charAt(0);
csv.setFieldSeparatorRead(fieldSeparator);
}
String[] columns = StringUtils.arraySplit(columnList, fieldSeparator, true);
ValueResultSet vr = ValueResultSet.get(csv.read(fileName, columns, charset));
return vr;
}
case CSVWRITE: {
Connection conn = session.createConnection(false);
String charset = v2 == null ? null : v2.getString();
Csv.getInstance().write(conn, v0.getString(), v1.getString(), charset);
String fieldSeparatorWrite = v3 == null ? null : v3.getString();
Csv csv = Csv.getInstance();
if(fieldSeparatorWrite != null) {
csv.setFieldSeparatorWrite(fieldSeparatorWrite);
}
csv.write(conn, v0.getString(), v1.getString(), charset);
return ValueNull.INSTANCE;
}
case MEMORY_FREE:
......@@ -1386,9 +1396,16 @@ public class Function extends Expression implements FunctionCall {
throw Message.getSQLException(Message.PARAMETER_NOT_SET_1, "fileName");
}
String columnList = args.length < 2 ? null : args[1].getValue(session).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', true);
String charset = args.length < 3 ? null : args[2].getValue(session).getString();
ResultSet rs = Csv.getInstance().read(fileName, columns, charset);
String fieldSeparatorRead = args.length < 4 ? null : args[3].getValue(session).getString();
Csv csv = Csv.getInstance();
char fieldSeparator = ',';
if(fieldSeparatorRead != null && fieldSeparatorRead.length() > 0) {
fieldSeparator = fieldSeparatorRead.charAt(0);
csv.setFieldSeparatorRead(fieldSeparator);
}
String[] columns = StringUtils.arraySplit(columnList, fieldSeparator, true);
ResultSet rs = csv.read(fileName, columns, charset);
ValueResultSet vr = ValueResultSet.getCopy(rs, 0);
return vr;
}
......
......@@ -25,7 +25,7 @@ public class SequenceValue extends Expression {
public Value getValue(Session session) throws SQLException {
long value = sequence.getNext();
session.setLastIdentity(value);
session.setLastIdentity(ValueLong.get(value));
return ValueLong.get(value);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论