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

--no commit message

--no commit message
上级 c9dd1fe3
...@@ -17,6 +17,8 @@ History ...@@ -17,6 +17,8 @@ History
Change Log</a><br> Change Log</a><br>
<a href="#roadmap"> <a href="#roadmap">
Roadmap</a><br> Roadmap</a><br>
<a href="#supporters">
Supporters</a><br>
<br><a name="history"></a> <br><a name="history"></a>
<h2>History of this Database Engine</h2> <h2>History of this Database Engine</h2>
...@@ -34,6 +36,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -34,6 +36,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3> <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> <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). <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! Thanks a lot to Martina Nissler for finding this problem!
...@@ -1227,6 +1239,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1227,6 +1239,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Enable and document optimizations, LOB files in directories <li>Enable and document optimizations, LOB files in directories
<li>Special methods for DataPage.writeByte / writeShort and so on <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>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> </ul>
<h3>Priority 1</h3> <h3>Priority 1</h3>
...@@ -1491,6 +1505,11 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1491,6 +1505,11 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<li>Delay reading the row if data is not required <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>Eliminate undo log records if stored on disk (just one pointer per block, not per record)
<li>User defined aggregate functions <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> </ul>
<h3>Not Planned</h3> <h3>Not Planned</h3>
...@@ -1499,4 +1518,15 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -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 <li>String.intern (so that Strings can be compared with ==) will not be used because some VMs have problems when used extensively
</ul> </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> </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; ...@@ -15,7 +15,7 @@ import java.util.EventListener;
public interface DatabaseEventListener extends 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. * This method is called just after creating the object.
...@@ -35,7 +35,7 @@ public interface DatabaseEventListener extends EventListener { ...@@ -35,7 +35,7 @@ public interface DatabaseEventListener extends EventListener {
void diskSpaceIsLow(long stillAvailable) throws SQLException; 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 * @param e the exception
*/ */
......
...@@ -124,7 +124,7 @@ public class Bnf { ...@@ -124,7 +124,7 @@ public class Bnf {
addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL); addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL);
addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END); addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END);
addFixedRule("anything", RuleFixed.ANY_WORD); addFixedRule("anything", RuleFixed.ANY_WORD);
addFixedRule("@hexStart@", RuleFixed.HEXSTART); addFixedRule("@hexStart@", RuleFixed.HEX_START);
addFixedRule("@concat@", RuleFixed.CONCAT); addFixedRule("@concat@", RuleFixed.CONCAT);
addFixedRule("@az_@", RuleFixed.AZ_); addFixedRule("@az_@", RuleFixed.AZ_);
addFixedRule("@af@", RuleFixed.AF); addFixedRule("@af@", RuleFixed.AF);
...@@ -215,7 +215,7 @@ public class Bnf { ...@@ -215,7 +215,7 @@ public class Bnf {
if(firstChar != '}') { if(firstChar != '}') {
throw new Error("expected }, got " + currentToken+ " syntax:" + syntax); 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 RuleList(new RuleElement(",", currentTopic), lastRepeat, false);
r = new RuleRepeat(r); r = new RuleRepeat(r);
} else if("@dots@".equals(currentToken)) { } else if("@dots@".equals(currentToken)) {
...@@ -245,7 +245,7 @@ public class Bnf { ...@@ -245,7 +245,7 @@ public class Bnf {
syntax = StringUtils.replaceAll(syntax, "nnnnnnnnn", "@nanos@"); syntax = StringUtils.replaceAll(syntax, "nnnnnnnnn", "@nanos@");
syntax = StringUtils.replaceAll(syntax, "function", "@func@"); syntax = StringUtils.replaceAll(syntax, "function", "@func@");
syntax = StringUtils.replaceAll(syntax, "0x", "@hexStart@"); 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, "...", "@dots@");
syntax = StringUtils.replaceAll(syntax, "||", "@concat@"); syntax = StringUtils.replaceAll(syntax, "||", "@concat@");
syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@"); syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@");
......
...@@ -16,7 +16,7 @@ public class RuleFixed implements Rule { ...@@ -16,7 +16,7 @@ public class RuleFixed implements Rule {
public static final int ANY_UNTIL_EOL = 5; public static final int ANY_UNTIL_EOL = 5;
public static final int ANY_UNTIL_END = 6; public static final int ANY_UNTIL_END = 6;
public static final int ANY_WORD = 7; 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; private int type;
...@@ -45,7 +45,7 @@ public class RuleFixed implements Rule { ...@@ -45,7 +45,7 @@ public class RuleFixed implements Rule {
} }
return buff.toString(); return buff.toString();
} }
case HEXSTART: case HEX_START:
return "0x"; return "0x";
case CONCAT: case CONCAT:
return "||"; return "||";
...@@ -134,7 +134,7 @@ public class RuleFixed implements Rule { ...@@ -134,7 +134,7 @@ public class RuleFixed implements Rule {
} }
} }
break; break;
case HEXSTART: case HEX_START:
if(StringUtils.toUpperEnglish(s).startsWith("0X")) { if(StringUtils.toUpperEnglish(s).startsWith("0X")) {
s = s.substring(2); s = s.substring(2);
} else if(StringUtils.toUpperEnglish(s).startsWith("0")) { } else if(StringUtils.toUpperEnglish(s).startsWith("0")) {
...@@ -209,7 +209,7 @@ public class RuleFixed implements Rule { ...@@ -209,7 +209,7 @@ public class RuleFixed implements Rule {
break; break;
case ANY_WORD: case ANY_WORD:
break; break;
case HEXSTART: case HEX_START:
if(query.length() == 0) { if(query.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD); sentence.add("0x", "0x", Sentence.KEYWORD);
} else if(query.equals("0")) { } else if(query.equals("0")) {
......
...@@ -89,7 +89,7 @@ public class CommandRemote implements CommandInterface { ...@@ -89,7 +89,7 @@ public class CommandRemote implements CommandInterface {
if(session.isClustered() || scrollable) { if(session.isClustered() || scrollable) {
readRows = Integer.MAX_VALUE; readRows = Integer.MAX_VALUE;
} else { } else {
readRows = Constants.SERVER_SMALL_RESULTSET_SIZE; readRows = Constants.SERVER_SMALL_RESULT_SET_SIZE;
} }
transfer.writeInt(readRows); transfer.writeInt(readRows);
sendParameters(transfer); sendParameters(transfer);
...@@ -173,7 +173,7 @@ public class CommandRemote implements CommandInterface { ...@@ -173,7 +173,7 @@ public class CommandRemote implements CommandInterface {
session.traceOperation("COMMAND_CLOSE", id); session.traceOperation("COMMAND_CLOSE", id);
transfer.writeInt(SessionRemote.COMMAND_CLOSE).writeInt(id); transfer.writeInt(SessionRemote.COMMAND_CLOSE).writeInt(id);
} catch (IOException e) { } 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); trace.error("close", e);
} }
} }
...@@ -182,7 +182,7 @@ public class CommandRemote implements CommandInterface { ...@@ -182,7 +182,7 @@ public class CommandRemote implements CommandInterface {
} }
// public void finalize() { // public void finalize() {
// if(!Database.RUN_FINALIZERS) { // if(!Constants.RUN_FINALIZE) {
// return; // return;
// } // }
// close(); // close();
......
...@@ -46,6 +46,7 @@ import org.h2.command.ddl.DropView; ...@@ -46,6 +46,7 @@ import org.h2.command.ddl.DropView;
import org.h2.command.ddl.GrantRevoke; import org.h2.command.ddl.GrantRevoke;
import org.h2.command.ddl.SetComment; import org.h2.command.ddl.SetComment;
import org.h2.command.ddl.TruncateTable; import org.h2.command.ddl.TruncateTable;
import org.h2.command.dml.Backup;
import org.h2.command.dml.Call; import org.h2.command.dml.Call;
import org.h2.command.dml.Delete; import org.h2.command.dml.Delete;
import org.h2.command.dml.ExplainPlan; import org.h2.command.dml.ExplainPlan;
...@@ -135,7 +136,7 @@ public class Parser { ...@@ -135,7 +136,7 @@ public class Parser {
private static final int EQUAL = 6, BIGGER_EQUAL = 7, BIGGER = 8; private static final int EQUAL = 6, BIGGER_EQUAL = 7, BIGGER = 8;
private static final int SMALLER = 9, SMALLER_EQUAL = 10, NOT_EQUAL = 11; private static final int SMALLER = 9, SMALLER_EQUAL = 10, NOT_EQUAL = 11;
private static final int MINUS = 17, PLUS = 18; private static final int MINUS = 17, PLUS = 18;
private static final int STRINGCONCAT = 22; private static final int STRING_CONCAT = 22;
private static final int OPEN = 31, CLOSE = 32, NULL = 34, TRUE = 40, FALSE = 41; private static final int OPEN = 31, CLOSE = 32, NULL = 34, TRUE = 40, FALSE = 41;
private static final int CURRENT_TIMESTAMP = 42, CURRENT_DATE = 43, CURRENT_TIME = 44, ROWNUM = 45; private static final int CURRENT_TIMESTAMP = 42, CURRENT_DATE = 43, CURRENT_TIME = 44, ROWNUM = 45;
...@@ -257,7 +258,12 @@ public class Parser { ...@@ -257,7 +258,12 @@ public class Parser {
if(readIf("ALTER")) { if(readIf("ALTER")) {
c = parseAlter(); c = parseAlter();
} else if(readIf("ANALYZE")) { } else if(readIf("ANALYZE")) {
c = parseAnalyse(); c = parseAnalyze();
}
break;
case 'B':
if(readIf("BACKUP")) {
c = parseBackup();
} }
break; break;
case 'C': case 'C':
...@@ -414,8 +420,15 @@ public class Parser { ...@@ -414,8 +420,15 @@ public class Parser {
return Message.getSyntaxError(sqlCommand, parseIndex, buff.toString()); return Message.getSyntaxError(sqlCommand, parseIndex, buff.toString());
} }
} }
private Prepared parseBackup() throws SQLException {
Backup command = new Backup(session);
read("TO");
command.setFileName(readString());
return command;
}
private Prepared parseAnalyse() throws SQLException { private Prepared parseAnalyze() throws SQLException {
Analyze command = new Analyze(session); Analyze command = new Analyze(session);
if(readIf("SAMPLE_SIZE")) { if(readIf("SAMPLE_SIZE")) {
command.setTop(getPositiveInt()); command.setTop(getPositiveInt());
...@@ -706,7 +719,7 @@ public class Parser { ...@@ -706,7 +719,7 @@ public class Parser {
return command; return command;
} }
private TableFilter readTableFilter() throws SQLException { private TableFilter readTableFilter(boolean fromOuter) throws SQLException {
Table table; Table table;
Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN); Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN);
if(readIf("(")) { if(readIf("(")) {
...@@ -716,8 +729,8 @@ public class Parser { ...@@ -716,8 +729,8 @@ public class Parser {
table = new TableView(mainSchema, 0, "TEMP_VIEW", querySQL, query.getParameters(), null, session); table = new TableView(mainSchema, 0, "TEMP_VIEW", querySQL, query.getParameters(), null, session);
read(")"); read(")");
} else { } else {
TableFilter top = readTableFilter(); TableFilter top = readTableFilter(fromOuter);
top = readJoin(top, currentSelect); top = readJoin(top, currentSelect, fromOuter);
read(")"); read(")");
return top; return top;
} }
...@@ -943,13 +956,14 @@ public class Parser { ...@@ -943,13 +956,14 @@ public class Parser {
return command; return command;
} }
private TableFilter readJoin(TableFilter top, Select command) throws SQLException { private TableFilter readJoin(TableFilter top, Select command, boolean fromOuter) throws SQLException {
TableFilter last = top; TableFilter last = top;
while (true) { while (true) {
if (readIf("RIGHT")) { if (readIf("RIGHT")) {
readIf("OUTER"); readIf("OUTER");
read("JOIN"); read("JOIN");
TableFilter newTop = readTableFilter(); // the right hand side is the 'inner' table usually
TableFilter newTop = readTableFilter(fromOuter);
Expression on = null; Expression on = null;
if(readIf("ON")) { if(readIf("ON")) {
on = readExpression(); on = readExpression();
...@@ -960,7 +974,7 @@ public class Parser { ...@@ -960,7 +974,7 @@ public class Parser {
} else if (readIf("LEFT")) { } else if (readIf("LEFT")) {
readIf("OUTER"); readIf("OUTER");
read("JOIN"); read("JOIN");
TableFilter join = readTableFilter(); TableFilter join = readTableFilter(true);
Expression on = null; Expression on = null;
if(readIf("ON")) { if(readIf("ON")) {
on = readExpression(); on = readExpression();
...@@ -969,52 +983,51 @@ public class Parser { ...@@ -969,52 +983,51 @@ public class Parser {
last = join; last = join;
} else if (readIf("INNER")) { } else if (readIf("INNER")) {
read("JOIN"); read("JOIN");
TableFilter join = readTableFilter(fromOuter);
TableFilter join = readTableFilter();
Expression on = null; Expression on = null;
if(readIf("ON")) { if(readIf("ON")) {
on = readExpression(); on = readExpression();
} }
top.addJoin(join, false, on); top.addJoin(join, fromOuter, on);
last = join; last = join;
} else if(readIf("JOIN")) { } else if(readIf("JOIN")) {
TableFilter join = readTableFilter(); TableFilter join = readTableFilter(fromOuter);
Expression on = null; Expression on = null;
if(readIf("ON")) { if(readIf("ON")) {
on = readExpression(); on = readExpression();
} }
top.addJoin(join, false, on); top.addJoin(join, fromOuter, on);
last = join; last = join;
} else if(readIf("CROSS")) { } else if(readIf("CROSS")) {
read("JOIN"); read("JOIN");
TableFilter join = readTableFilter(); TableFilter join = readTableFilter(fromOuter);
top.addJoin(join, false, null); top.addJoin(join, fromOuter, null);
last = join; last = join;
} else if(readIf("NATURAL")) { } else if(readIf("NATURAL")) {
read("JOIN"); read("JOIN");
TableFilter join = readTableFilter(); TableFilter join = readTableFilter(fromOuter);
Column[] tc = last.getTable().getColumns(); Column[] tableCols = last.getTable().getColumns();
Column[] jc = join.getTable().getColumns(); Column[] joinCols = join.getTable().getColumns();
String ts = last.getTable().getSchema().getName(); String tableSchema = last.getTable().getSchema().getName();
String js = join.getTable().getSchema().getName(); String joinSchema = join.getTable().getSchema().getName();
Expression on = null; Expression on = null;
for(int t=0; t<tc.length; t++) { for(int t=0; t<tableCols.length; t++) {
String tcn = tc[t].getName(); String tableColumnName = tableCols[t].getName();
for(int j=0; j<jc.length; j++) { for(int j=0; j<joinCols.length; j++) {
String jcn = jc[j].getName(); String joinColumnName = joinCols[j].getName();
if(tcn.equals(jcn)) { if(tableColumnName.equals(joinColumnName)) {
Expression te = new ExpressionColumn(database, currentSelect, ts, last.getTableAlias(), tcn); Expression tableExpr = new ExpressionColumn(database, currentSelect, tableSchema, last.getTableAlias(), tableColumnName);
Expression je = new ExpressionColumn(database, currentSelect, js, join.getTableAlias(), jcn); Expression joinExpr = new ExpressionColumn(database, currentSelect, joinSchema, join.getTableAlias(), joinColumnName);
Expression eq = new Comparison(session, Comparison.EQUAL, te, je); Expression equal = new Comparison(session, Comparison.EQUAL, tableExpr, joinExpr);
if(on == null) { if(on == null) {
on = eq; on = equal;
} else { } else {
on = new ConditionAndOr(ConditionAndOr.AND, on, eq); on = new ConditionAndOr(ConditionAndOr.AND, on, equal);
} }
} }
} }
} }
top.addJoin(join, false, on); top.addJoin(join, fromOuter, on);
last = join; last = join;
} else { } else {
break; break;
...@@ -1023,32 +1036,6 @@ public class Parser { ...@@ -1023,32 +1036,6 @@ public class Parser {
return top; return top;
} }
private void parseJoinTableFilter(TableFilter top, Select command) throws SQLException {
top = readJoin(top, command);
command.addTableFilter(top, true);
boolean isOuter = false;
while(true) {
TableFilter join = top.getJoin();
if(join == null) {
break;
}
isOuter = isOuter | join.isJoinOuter();
if(isOuter) {
command.addTableFilter(join, false);
} else {
// make flat so the optimizer can work better
Expression on = join.getJoinCondition();
if(on != null) {
command.addCondition(on);
}
join.removeJoinCondition();
top.removeJoin();
command.addTableFilter(join, true);
}
top = join;
}
}
private ExplainPlan parseExplain() throws SQLException { private ExplainPlan parseExplain() throws SQLException {
ExplainPlan command = new ExplainPlan(session); ExplainPlan command = new ExplainPlan(session);
readIf("PLAN"); readIf("PLAN");
...@@ -1210,10 +1197,36 @@ public class Parser { ...@@ -1210,10 +1197,36 @@ public class Parser {
private void parseSelectSimpleFromPart(Select command) throws SQLException { private void parseSelectSimpleFromPart(Select command) throws SQLException {
do { do {
TableFilter filter = readTableFilter(); TableFilter filter = readTableFilter(false);
parseJoinTableFilter(filter, command); parseJoinTableFilter(filter, command);
} while(readIf(",")); } while(readIf(","));
} }
private void parseJoinTableFilter(TableFilter top, Select command) throws SQLException {
top = readJoin(top, command, top.isJoinOuter());
command.addTableFilter(top, true);
boolean isOuter = false;
while(true) {
TableFilter join = top.getJoin();
if(join == null) {
break;
}
isOuter = isOuter | join.isJoinOuter();
if(isOuter) {
command.addTableFilter(join, false);
} else {
// make flat so the optimizer can work better
Expression on = join.getJoinCondition();
if(on != null) {
command.addCondition(on);
}
join.removeJoinCondition();
top.removeJoin();
command.addTableFilter(join, true);
}
top = join;
}
}
private void parseSelectSimpleSelectPart(Select command) throws SQLException { private void parseSelectSimpleSelectPart(Select command) throws SQLException {
if(readIf("TOP")) { if(readIf("TOP")) {
...@@ -1362,7 +1375,7 @@ public class Parser { ...@@ -1362,7 +1375,7 @@ public class Parser {
Expression b = readConcat(); Expression b = readConcat();
Expression esc = null; Expression esc = null;
if (readIf("ESCAPE")) { if (readIf("ESCAPE")) {
esc = readExpression(); esc = readConcat();
} }
recompileAlways = true; recompileAlways = true;
r = new CompareLike(database.getCompareMode(), r, b, esc); r = new CompareLike(database.getCompareMode(), r, b, esc);
...@@ -1433,20 +1446,20 @@ public class Parser { ...@@ -1433,20 +1446,20 @@ public class Parser {
if(readIf("(") && readIf("+") && readIf(")")) { if(readIf("(") && readIf("+") && readIf(")")) {
// support for a subset of old-fashioned Oracle outer join with (+) // support for a subset of old-fashioned Oracle outer join with (+)
if(r instanceof ExpressionColumn && right instanceof ExpressionColumn) { if(r instanceof ExpressionColumn && right instanceof ExpressionColumn) {
ExpressionColumn lcol = (ExpressionColumn) r; ExpressionColumn leftCol = (ExpressionColumn) r;
ExpressionColumn rcol = (ExpressionColumn) right; ExpressionColumn rightCol = (ExpressionColumn) right;
ObjectArray filters = currentSelect.getTopFilters(); ObjectArray filters = currentSelect.getTopFilters();
for(int i=0; filters != null && i<filters.size(); i++) { for(int i=0; filters != null && i<filters.size(); i++) {
TableFilter f = (TableFilter) filters.get(i); TableFilter f = (TableFilter) filters.get(i);
lcol.mapColumns(f, 0); leftCol.mapColumns(f, 0);
rcol.mapColumns(f, 0); rightCol.mapColumns(f, 0);
} }
TableFilter lfilter = lcol.getTableFilter(); TableFilter leftFilter = leftCol.getTableFilter();
TableFilter rfilter = rcol.getTableFilter(); TableFilter rightFilter = rightCol.getTableFilter();
r = new Comparison(session, compareType, r, right); r = new Comparison(session, compareType, r, right);
if(lfilter != null && rfilter != null) { if(leftFilter != null && rightFilter != null) {
filters.remove(filters.indexOf(rfilter)); filters.remove(filters.indexOf(rightFilter));
lfilter.addJoin(rfilter, true, r); leftFilter.addJoin(rightFilter, true, r);
r = ValueExpression.get(ValueBoolean.get(true)); r = ValueExpression.get(ValueBoolean.get(true));
} }
} }
...@@ -1548,7 +1561,7 @@ public class Parser { ...@@ -1548,7 +1561,7 @@ public class Parser {
private JavaFunction readJavaFunction(String name) throws SQLException { private JavaFunction readJavaFunction(String name) throws SQLException {
FunctionAlias functionAlias = database.findFunctionAlias(name); FunctionAlias functionAlias = database.findFunctionAlias(name);
if(functionAlias == null) { if(functionAlias == null) {
// TODO compatiblity: maybe support 'on the fly java functions' as HSQLDB ( CALL "java.lang.Math.sqrt"(2.0) ) // TODO compatibility: maybe support 'on the fly java functions' as HSQLDB ( CALL "java.lang.Math.sqrt"(2.0) )
throw Message.getSQLException(Message.FUNCTION_NOT_FOUND_1, name); throw Message.getSQLException(Message.FUNCTION_NOT_FOUND_1, name);
} }
int paramCount = functionAlias.getParameterCount(); int paramCount = functionAlias.getParameterCount();
...@@ -1611,7 +1624,7 @@ public class Parser { ...@@ -1611,7 +1624,7 @@ public class Parser {
break; break;
} }
case Function.POSITION: { case Function.POSITION: {
// can't read expession because IN would be read too early // can't read expression because IN would be read too early
function.setParameter(0, readConcat()); function.setParameter(0, readConcat());
if(!readIf(",")) { if(!readIf(",")) {
read("IN"); read("IN");
...@@ -1728,7 +1741,7 @@ public class Parser { ...@@ -1728,7 +1741,7 @@ public class Parser {
if(indexed && currentTokenType == VALUE && currentValue.getType() == Value.INT) { if(indexed && currentTokenType == VALUE && currentValue.getType() == Value.INT) {
if(indexedParameterList == null) { if(indexedParameterList == null) {
if(parameters.size()>0) { if(parameters.size()>0) {
throw Message.getSQLException(Message.CANT_MIX_INDEXED_AND_UNINDEXED_PARAMS); throw Message.getSQLException(Message.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
} }
indexedParameterList = new ObjectArray(); indexedParameterList = new ObjectArray();
} }
...@@ -1747,7 +1760,7 @@ public class Parser { ...@@ -1747,7 +1760,7 @@ public class Parser {
read(); read();
} else { } else {
if(indexedParameterList != null) { if(indexedParameterList != null) {
throw Message.getSQLException(Message.CANT_MIX_INDEXED_AND_UNINDEXED_PARAMS); throw Message.getSQLException(Message.CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS);
} }
r = new Parameter(parameters.size()); r = new Parameter(parameters.size());
} }
...@@ -2332,7 +2345,7 @@ public class Parser { ...@@ -2332,7 +2345,7 @@ public class Parser {
} }
break; break;
} }
// fallthrough // fall through
case '-': case '-':
if (command[i + 1] == '-') { if (command[i + 1] == '-') {
// single line comment // single line comment
...@@ -2348,7 +2361,7 @@ public class Parser { ...@@ -2348,7 +2361,7 @@ public class Parser {
} }
break; break;
} }
// fallthrough // fall through
case '(': case '(':
case ')': case ')':
case '{': case '{':
...@@ -2507,7 +2520,7 @@ public class Parser { ...@@ -2507,7 +2520,7 @@ public class Parser {
break; break;
case '|': case '|':
if(s.equals("||")) { if(s.equals("||")) {
return STRINGCONCAT; return STRING_CONCAT;
} }
} }
} }
...@@ -2703,8 +2716,8 @@ public class Parser { ...@@ -2703,8 +2716,8 @@ public class Parser {
column.setSequence(sequence); column.setSequence(sequence);
} }
if(readIf("SELECTIVITY")) { if(readIf("SELECTIVITY")) {
int sel = getPositiveInt(); int value = getPositiveInt();
column.setSelectivity(sel); column.setSelectivity(value);
} }
column.setComment(readCommentIf()); column.setComment(readCommentIf());
return column; return column;
......
...@@ -124,7 +124,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -124,7 +124,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
checkNoViews(); checkNoViews();
if(table.getColumns().length == 1) { if(table.getColumns().length == 1) {
// TODO test each sql exception // 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); table.checkColumnIsNotReferenced(oldColumn);
dropSingleColumnIndexes(); dropSingleColumnIndexes();
......
...@@ -56,7 +56,7 @@ public class DropTable extends SchemaCommand { ...@@ -56,7 +56,7 @@ public class DropTable extends SchemaCommand {
} else { } else {
session.getUser().checkRight(table, Right.ALL); session.getUser().checkRight(table, Right.ALL);
if(!table.canDrop()) { 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); table.lock(session, true);
} }
......
...@@ -39,7 +39,7 @@ public class DropUser extends DefineCommand { ...@@ -39,7 +39,7 @@ public class DropUser extends DefineCommand {
} }
} else { } else {
if(user == session.getUser()) { if(user == session.getUser()) {
throw Message.getSQLException(Message.CANT_DROP_CURRENT_USER); throw Message.getSQLException(Message.CANNOT_DROP_CURRENT_USER);
} }
db.removeDatabaseObject(session, user); db.removeDatabaseObject(session, user);
} }
......
...@@ -28,7 +28,7 @@ public class TruncateTable extends SchemaCommand { ...@@ -28,7 +28,7 @@ public class TruncateTable extends SchemaCommand {
session.commit(); session.commit();
Table table = getSchema().getTableOrView(session, tableName); Table table = getSchema().getTableOrView(session, tableName);
if(!table.canTruncate()) { if(!table.canTruncate()) {
throw Message.getSQLException(Message.CANT_TRUNCATE_1, tableName); throw Message.getSQLException(Message.CANNOT_TRUNCATE_1, tableName);
} else { } else {
session.getUser().checkRight(table, Right.DELETE); session.getUser().checkRight(table, Right.DELETE);
table.lock(session, true); table.lock(session, true);
......
...@@ -91,24 +91,24 @@ public class Optimizer { ...@@ -91,24 +91,24 @@ public class Optimizer {
} }
private void calculateBruteForceAll() throws SQLException { private void calculateBruteForceAll() throws SQLException {
TableFilter[] ftry = new TableFilter[filters.length]; TableFilter[] list = new TableFilter[filters.length];
Permutations perm = new Permutations(filters, ftry); Permutations p = new Permutations(filters, list);
for(int x=0; !canStop(x) && perm.next(); x++) { for(int x=0; !canStop(x) && p.next(); x++) {
testPlan(ftry); testPlan(list);
} }
} }
private void calculateBruteForceSome() throws SQLException { private void calculateBruteForceSome() throws SQLException {
int bruteForce = getMaxBruteForceFilters(filters.length); int bruteForce = getMaxBruteForceFilters(filters.length);
TableFilter[] ftry = new TableFilter[filters.length]; TableFilter[] list = new TableFilter[filters.length];
Permutations perm = new Permutations(filters, ftry, bruteForce); Permutations p = new Permutations(filters, list, bruteForce);
for(int x=0; !canStop(x) && perm.next(); x++) { for(int x=0; !canStop(x) && p.next(); x++) {
// find out what filters are not used yet // find out what filters are not used yet
for(int i=0; i<filters.length; i++) { for(int i=0; i<filters.length; i++) {
filters[i].setUsed(false); filters[i].setUsed(false);
} }
for(int i=0; i<bruteForce; i++) { for(int i=0; i<bruteForce; i++) {
ftry[i].setUsed(true); list[i].setUsed(true);
} }
// fill the remaining elements with the unused elements (greedy) // fill the remaining elements with the unused elements (greedy)
for(int i=bruteForce; i<filters.length; i++) { for(int i=bruteForce; i<filters.length; i++) {
...@@ -120,8 +120,8 @@ public class Optimizer { ...@@ -120,8 +120,8 @@ public class Optimizer {
bestPart = j; bestPart = j;
break; break;
} }
ftry[i] = filters[j]; list[i] = filters[j];
Plan part = new Plan(ftry, i+1, condition); Plan part = new Plan(list, i+1, condition);
double costNow = part.calculateCost(session); double costNow = part.calculateCost(session);
if (costPart < 0 || costNow < costPart) { if (costPart < 0 || costNow < costPart) {
costPart = costNow; costPart = costNow;
...@@ -130,41 +130,41 @@ public class Optimizer { ...@@ -130,41 +130,41 @@ public class Optimizer {
} }
} }
filters[bestPart].setUsed(true); filters[bestPart].setUsed(true);
ftry[i] = filters[bestPart]; list[i] = filters[bestPart];
} }
testPlan(ftry); testPlan(list);
} }
} }
private void calculateGenetic() throws SQLException { private void calculateGenetic() throws SQLException {
TableFilter[] fbest = new TableFilter[filters.length]; TableFilter[] best = new TableFilter[filters.length];
TableFilter[] ftry = new TableFilter[filters.length]; TableFilter[] list = new TableFilter[filters.length];
for(int x=0; x<MAX_GENETIC; x++) { for(int x=0; x<MAX_GENETIC; x++) {
if(canStop(x)) { if(canStop(x)) {
break; break;
} }
boolean generateRandom = (x & 127) == 0; boolean generateRandom = (x & 127) == 0;
if(!generateRandom) { if(!generateRandom) {
System.arraycopy(fbest, 0, ftry, 0, filters.length); System.arraycopy(best, 0, list, 0, filters.length);
if(!shuffleTwo(ftry)) { if(!shuffleTwo(list)) {
generateRandom = true; generateRandom = true;
} }
} }
if(generateRandom) { if(generateRandom) {
switched = new BitSet(); switched = new BitSet();
System.arraycopy(filters, 0, fbest, 0, filters.length); System.arraycopy(filters, 0, best, 0, filters.length);
shuffleAll(fbest); shuffleAll(best);
System.arraycopy(fbest, 0, ftry, 0, filters.length); System.arraycopy(best, 0, list, 0, filters.length);
} }
if(testPlan(ftry)) { if(testPlan(list)) {
switched = new BitSet(); 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 { private boolean testPlan(TableFilter[] list) throws SQLException {
Plan p = new Plan(ftry, ftry.length, condition); Plan p = new Plan(list, list.length, condition);
double costNow = p.calculateCost(session); double costNow = p.calculateCost(session);
if (cost < 0 || costNow < cost) { if (cost < 0 || costNow < cost) {
cost = costNow; cost = costNow;
......
...@@ -109,9 +109,9 @@ public abstract class Query extends Prepared { ...@@ -109,9 +109,9 @@ public abstract class Query extends Prepared {
boolean isAlias = false; boolean isAlias = false;
idx = expressions.size(); idx = expressions.size();
if(e instanceof ExpressionColumn) { if(e instanceof ExpressionColumn) {
ExpressionColumn ecol = (ExpressionColumn)e; ExpressionColumn exprCol = (ExpressionColumn)e;
String alias = ecol.getOriginalAliasName(); String alias = exprCol.getOriginalAliasName();
String col = ecol.getOriginalColumnName(); String col = exprCol.getOriginalColumnName();
for(int j=0; j<visible; j++) { for(int j=0; j<visible; j++) {
boolean found = false; boolean found = false;
Expression ec = (Expression) expressions.get(j); Expression ec = (Expression) expressions.get(j);
......
...@@ -316,7 +316,7 @@ public class Select extends Query { ...@@ -316,7 +316,7 @@ public class Select extends Query {
} }
topTableFilter.startQuery(); topTableFilter.startQuery();
topTableFilter.reset(); topTableFilter.reset();
// TODO lock tables of subqueries // TODO lock tables of sub queries
topTableFilter.lock(session, isForUpdate); topTableFilter.lock(session, isForUpdate);
if(isQuickQuery) { if(isQuickQuery) {
queryQuick(columnCount, result); queryQuick(columnCount, result);
...@@ -557,10 +557,10 @@ public class Select extends Query { ...@@ -557,10 +557,10 @@ public class Select extends Query {
int id=0; int id=0;
do { do {
if(id > 0) { if(id > 0) {
buff.append('\n'); buff.append("\n");
} }
id++;
buff.append(filter.getPlanSQL(join)); buff.append(filter.getPlanSQL(join));
id++;
join = true; join = true;
filter = filter.getJoin(); filter = filter.getJoin();
} while(filter != null); } while(filter != null);
...@@ -570,16 +570,16 @@ public class Select extends Query { ...@@ -570,16 +570,16 @@ public class Select extends Query {
if(groupIndex != null) { if(groupIndex != null) {
buff.append("\nGROUP BY "); buff.append("\nGROUP BY ");
for(int i=0; i<groupIndex.length; i++) { for(int i=0; i<groupIndex.length; i++) {
Expression gro = exprList[groupIndex[i]]; Expression g = exprList[groupIndex[i]];
if(i>0) { if(i>0) {
buff.append(", "); buff.append(", ");
} }
buff.append(StringUtils.unEnclose(gro.getSQL())); buff.append(StringUtils.unEnclose(g.getSQL()));
} }
} }
if(havingIndex >= 0) { if(havingIndex >= 0) {
Expression hav = exprList[havingIndex]; Expression h = exprList[havingIndex];
buff.append("\nHAVING " + StringUtils.unEnclose(hav.getSQL())); buff.append("\nHAVING " + StringUtils.unEnclose(h.getSQL()));
} }
if(sort != null) { if(sort != null) {
buff.append("\nORDER BY "); buff.append("\nORDER BY ");
......
...@@ -8,7 +8,7 @@ import java.sql.SQLException; ...@@ -8,7 +8,7 @@ import java.sql.SQLException;
import java.text.Collator; import java.text.Collator;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.compress.Compresser; import org.h2.compress.Compressor;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
...@@ -220,7 +220,7 @@ public class Set extends Prepared { ...@@ -220,7 +220,7 @@ public class Set extends Prepared {
case SetTypes.COMPRESS_LOB: { case SetTypes.COMPRESS_LOB: {
session.getUser().checkAdmin(); session.getUser().checkAdmin();
int algo = CompressTool.getInstance().getCompressAlgorithm(stringValue); int algo = CompressTool.getInstance().getCompressAlgorithm(stringValue);
database.setLobCompressionAlgorithm(algo == Compresser.NO ? null : stringValue); database.setLobCompressionAlgorithm(algo == Compressor.NO ? null : stringValue);
addOrUpdateSetting(name, stringValue, 0); addOrUpdateSetting(name, stringValue, 0);
break; break;
} }
......
...@@ -6,6 +6,7 @@ package org.h2.command.dml; ...@@ -6,6 +6,7 @@ package org.h2.command.dml;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
...@@ -117,12 +118,6 @@ public class TransactionCommand extends Prepared { ...@@ -117,12 +118,6 @@ public class TransactionCommand extends Prepared {
session.close(); session.close();
break; break;
} }
// case BACKUP: {
// session.getUser().checkAdmin();
// session.commit();
// backupTo("backup.zip");
// break;
// }
default: default:
throw Message.getInternalError("type=" + type); throw Message.getInternalError("type=" + type);
} }
...@@ -130,15 +125,29 @@ public class TransactionCommand extends Prepared { ...@@ -130,15 +125,29 @@ public class TransactionCommand extends Prepared {
} }
private void backupTo(String fileName) throws SQLException { private void backupTo(String fileName) throws SQLException {
// int todoAddSpecialSQLStatement; int todoMoveToOwnCommand;
// FileOutputStream fileout = new FileOutputStream("test.zip"); try {
// ZipOutputStream out = new ZipOutputStream(fileout); FileOutputStream fileOut = new FileOutputStream("test.zip");
// out.putNextEntry(new ZipEntry("test.data.db")); ZipOutputStream out = new ZipOutputStream(fileOut);
// DiskFile file = session.getDatabase().getDataFile(); out.putNextEntry(new ZipEntry("test.data.db"));
// session.getDatabase().getLog().incStopDeleteFiles(true); DiskFile file = session.getDatabase().getDataFile();
// TODO Auto-generated method stub try {
// session.getDatabase().getLog().setStopDeleteFiles(false); 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() { public boolean isTransactional() {
......
...@@ -9,7 +9,7 @@ import java.util.zip.*; ...@@ -9,7 +9,7 @@ import java.util.zip.*;
import org.h2.message.Message; import org.h2.message.Message;
public class CompressDeflate implements Compresser { public class CompressDeflate implements Compressor {
private int level = Deflater.BEST_SPEED; private int level = Deflater.BEST_SPEED;
private int strategy = Deflater.DEFAULT_STRATEGY; private int strategy = Deflater.DEFAULT_STRATEGY;
...@@ -43,7 +43,7 @@ public class CompressDeflate implements Compresser { ...@@ -43,7 +43,7 @@ public class CompressDeflate implements Compresser {
} }
public int getAlgorithm() { 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 { public void expand(byte[] in, int inPos, int inLen, byte[] out, int outPos, int outLen) throws DataFormatException {
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* Copyright (c) 2000-2005 Marc Alexander Lehmann <schmorp@schmorp.de> * Copyright (c) 2000-2005 Marc Alexander Lehmann <schmorp@schmorp.de>
* Copyright (c) 2005 Oren J. Maurice <oymaurice@hazorea.org.il> * Copyright (c) 2005 Oren J. Maurice <oymaurice@hazorea.org.il>
* *
* Redistribution and use in source and binary forms, with or without modifica- * Redistribution and use in source and binary forms, with or without modification,
* tion, are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
...@@ -16,15 +16,15 @@ ...@@ -16,15 +16,15 @@
* 3. The name of the author may not be used to endorse or promote products * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * 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- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Alternatively, the contents of this file may be used under the terms of * Alternatively, the contents of this file may be used under the terms of
...@@ -40,13 +40,13 @@ ...@@ -40,13 +40,13 @@
package org.h2.compress; package org.h2.compress;
public class CompressLZF implements Compresser { public class CompressLZF implements Compressor {
public void setOptions(String options) { public void setOptions(String options) {
} }
public int getAlgorithm() { public int getAlgorithm() {
return Compresser.LZF; return Compressor.LZF;
} }
static final int HLOG = 14; static final int HLOG = 14;
...@@ -177,5 +177,3 @@ public class CompressLZF implements Compresser { ...@@ -177,5 +177,3 @@ public class CompressLZF implements Compresser {
} while (outPos < outLen); } while (outPos < outLen);
} }
} }
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
*/ */
package org.h2.compress; package org.h2.compress;
public class CompressNo implements Compresser { public class CompressNo implements Compressor {
public int getAlgorithm() { public int getAlgorithm() {
return Compresser.NO; return Compressor.NO;
} }
public void setOptions(String options) { public void setOptions(String options) {
......
...@@ -6,7 +6,7 @@ package org.h2.compress; ...@@ -6,7 +6,7 @@ package org.h2.compress;
import java.sql.SQLException; import java.sql.SQLException;
public interface Compresser { public interface Compressor {
int NO = 0, LZF = 1, DEFLATE = 2; int NO = 0, LZF = 1, DEFLATE = 2;
......
...@@ -499,8 +499,8 @@ public class ConstraintReferential extends Constraint { ...@@ -499,8 +499,8 @@ public class ConstraintReferential extends Constraint {
return refTable; return refTable;
} }
public boolean usesIndex(Index ind) { public boolean usesIndex(Index idx) {
return ind == index || ind == refIndex; return idx == index || idx == refIndex;
} }
public boolean containsColumn(Column col) { public boolean containsColumn(Column col) {
......
...@@ -113,8 +113,8 @@ public class ConstraintUnique extends Constraint { ...@@ -113,8 +113,8 @@ public class ConstraintUnique extends Constraint {
// unique index check is enough // unique index check is enough
} }
public boolean usesIndex(Index ind) { public boolean usesIndex(Index idx) {
return ind == index; return idx == index;
} }
public boolean containsColumn(Column col) { public boolean containsColumn(Column col) {
......
...@@ -59,6 +59,9 @@ public class ConnectionInfo { ...@@ -59,6 +59,9 @@ public class ConnectionInfo {
public ConnectionInfo(String u, Properties info) throws SQLException { public ConnectionInfo(String u, Properties info) throws SQLException {
this.originalURL = u; this.originalURL = u;
if(!u.startsWith(Constants.START_URL)) {
throw Message.getInvalidValueException(u, "url");
}
this.url = u; this.url = u;
readProperties(info); readProperties(info);
readSettings(); readSettings();
......
...@@ -32,7 +32,7 @@ package org.h2.engine; ...@@ -32,7 +32,7 @@ package org.h2.engine;
* - Check version, change build number in Constants.java and build.xml * - Check version, change build number in Constants.java and build.xml
* - Check code coverage * - Check code coverage
* - No " Message.getInternalError" (must be "throw Message.getInternalError") * - No " Message.getInternalError" (must be "throw Message.getInternalError")
* - ' #ifdef', ' #endif' * - space#ifdef', space#endif
* - No TODO in the docs * - No TODO in the docs
* - Run regression test with JDK 1.4 and 1.5 * - Run regression test with JDK 1.4 and 1.5
* - Change version(s) in performance.html; use latest versions of other databases * - Change version(s) in performance.html; use latest versions of other databases
...@@ -160,7 +160,7 @@ public class Constants { ...@@ -160,7 +160,7 @@ public class Constants {
public static final String TEMP_TABLE_PREFIX = "TEMP_TABLE_"; public static final String TEMP_TABLE_PREFIX = "TEMP_TABLE_";
public static final String TEMP_TABLE_TRANSACTION_PREFIX = "TEMP_TRANS_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_MAIN = "PUBLIC";
public static final String SCHEMA_INFORMATION = "INFORMATION_SCHEMA"; public static final String SCHEMA_INFORMATION = "INFORMATION_SCHEMA";
...@@ -199,7 +199,7 @@ public class Constants { ...@@ -199,7 +199,7 @@ public class Constants {
public static final int DEFAULT_ALLOW_LITERALS = ALLOW_LITERALS_ALL; public static final int DEFAULT_ALLOW_LITERALS = ALLOW_LITERALS_ALL;
public static final boolean AUTO_CONVERT_LOB_TO_FILES = true; 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_INTERNAL = "jdbc:default:connection";
public static final String CONN_URL_COLUMNLIST = "jdbc:columnlist:connection"; public static final String CONN_URL_COLUMNLIST = "jdbc:columnlist:connection";
...@@ -229,7 +229,7 @@ public class Constants { ...@@ -229,7 +229,7 @@ public class Constants {
public static final int LOB_FILES_PER_DIRECTORY = getIntSetting("h2.lobFilesPerDirectory", 256); 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 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_MIN_MAX = getBooleanSetting("h2.optimizeMinMax", true);
public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true); public static final boolean OPTIMIZE_IN = getBooleanSetting("h2.optimizeIn", true);
...@@ -240,7 +240,7 @@ public class Constants { ...@@ -240,7 +240,7 @@ public class Constants {
public static final boolean LOG_ALL_ERRORS = getBooleanSetting("h2.logAllErrors", false); 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 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_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_INITIAL = getIntSetting("h2.emergencySpaceInitial", 1 * 1024 * 1024);
public static final int EMERGENCY_SPACE_MIN = getIntSetting("h2.emergencySpaceMin", 128 * 1024); public static final int EMERGENCY_SPACE_MIN = getIntSetting("h2.emergencySpaceMin", 128 * 1024);
public static final boolean OBJECT_CACHE = getBooleanSetting("h2.objectCache", true); public static final boolean OBJECT_CACHE = getBooleanSetting("h2.objectCache", true);
......
...@@ -498,7 +498,7 @@ public class Database implements DataHandler { ...@@ -498,7 +498,7 @@ public class Database implements DataHandler {
starting = true; starting = true;
Cursor cursor = metaIdIndex.find(systemSession, null, null); Cursor cursor = metaIdIndex.find(systemSession, null, null);
// first, create all function aliases and sequences because // 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(); ObjectArray records = new ObjectArray();
while (cursor.next()) { while (cursor.next()) {
MetaRecord rec = new MetaRecord(cursor.get()); MetaRecord rec = new MetaRecord(cursor.get());
...@@ -813,9 +813,10 @@ public class Database implements DataHandler { ...@@ -813,9 +813,10 @@ public class Database implements DataHandler {
Engine.getInstance().close(databaseName); Engine.getInstance().close(databaseName);
if(deleteFilesOnDisconnect && persistent) { if(deleteFilesOnDisconnect && persistent) {
deleteFilesOnDisconnect = false; deleteFilesOnDisconnect = false;
String directory = FileUtils.getParent(databaseName);
try { try {
DeleteDbFiles.execute(directory, databaseShortName, true); String directory = FileUtils.getParent(databaseName);
String name = FileUtils.getFileName(databaseName);
DeleteDbFiles.execute(directory, name, true);
} catch(Exception e) { } catch(Exception e) {
// ignore (the trace is closed already) // ignore (the trace is closed already)
} }
...@@ -1123,7 +1124,7 @@ public class Database implements DataHandler { ...@@ -1123,7 +1124,7 @@ public class Database implements DataHandler {
String invalid = getFirstInvalidTable(); String invalid = getFirstInvalidTable();
if(invalid != null) { if(invalid != null) {
obj.getSchema().add(obj); 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(); int id = obj.getId();
obj.removeChildrenAndResources(session); obj.removeChildrenAndResources(session);
......
...@@ -29,6 +29,7 @@ import org.h2.table.Table; ...@@ -29,6 +29,7 @@ import org.h2.table.Table;
import org.h2.table.TableData; import org.h2.table.TableData;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLong;
/** /**
* @author Thomas * @author Thomas
...@@ -46,7 +47,7 @@ public class Session implements SessionInterface { ...@@ -46,7 +47,7 @@ public class Session implements SessionInterface {
private Random random; private Random random;
private LogSystem logSystem; private LogSystem logSystem;
private int lockTimeout; private int lockTimeout;
private long lastIdentity; private Value lastIdentity = ValueLong.get(0);
private int firstUncommittedLog = LogSystem.LOG_WRITTEN; private int firstUncommittedLog = LogSystem.LOG_WRITTEN;
private int firstUncommittedPos = LogSystem.LOG_WRITTEN; private int firstUncommittedPos = LogSystem.LOG_WRITTEN;
private HashMap savepoints; private HashMap savepoints;
...@@ -104,7 +105,7 @@ public class Session implements SessionInterface { ...@@ -104,7 +105,7 @@ public class Session implements SessionInterface {
} }
protected void finalize() { protected void finalize() {
if(!Constants.RUN_FINALIZERS) { if(!Constants.RUN_FINALIZE) {
return; return;
} }
if(database != null) { if(database != null) {
...@@ -328,11 +329,11 @@ public class Session implements SessionInterface { ...@@ -328,11 +329,11 @@ public class Session implements SessionInterface {
return database.getTrace(traceModuleName); return database.getTrace(traceModuleName);
} }
public void setLastIdentity(long last) { public void setLastIdentity(Value last) {
this.lastIdentity = last; this.lastIdentity = last;
} }
public long getLastIdentity() { public Value getLastIdentity() {
return lastIdentity; return lastIdentity;
} }
......
...@@ -37,7 +37,7 @@ import org.h2.value.ValueString; ...@@ -37,7 +37,7 @@ import org.h2.value.ValueString;
public class Aggregate extends Expression { public class Aggregate extends Expression {
// TODO aggregates: make them 'pluggable' // 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 // 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 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; public static final int GROUP_CONCAT = 6, STDDEV_POP = 7, STDDEV_SAMP = 8;
......
...@@ -149,7 +149,7 @@ public class CompareLike extends Condition { ...@@ -149,7 +149,7 @@ public class CompareLike extends Condition {
if(maxMatch == patternLength) { if(maxMatch == patternLength) {
filter.addIndexCondition(new IndexCondition(Comparison.EQUAL, l, ValueExpression.get(ValueString.get(begin)))); filter.addIndexCondition(new IndexCondition(Comparison.EQUAL, l, ValueExpression.get(ValueString.get(begin))));
} else { } 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; String end;
if(begin.length()>0) { if(begin.length()>0) {
filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(ValueString.get(begin)))); filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(ValueString.get(begin))));
...@@ -189,21 +189,21 @@ public class CompareLike extends Condition { ...@@ -189,21 +189,21 @@ public class CompareLike extends Condition {
} }
private boolean compare(String s, int pi, int si) { 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; 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++) { for (; pi < patternLength; pi++) {
int type = types[pi]; int type = types[pi];
switch (type) { switch (type) {
case MATCH: case MATCH:
if ((si >= slen) || !compare(s, pi, si++)) { if ((si >= sLen) || !compare(s, pi, si++)) {
return false; return false;
} }
break; break;
case ONE: case ONE:
if (si++ >= slen) { if (si++ >= sLen) {
return false; return false;
} }
break; break;
...@@ -211,8 +211,8 @@ public class CompareLike extends Condition { ...@@ -211,8 +211,8 @@ public class CompareLike extends Condition {
if (++pi >= patternLength) { if (++pi >= patternLength) {
return true; return true;
} }
while (si < slen) { while (si < sLen) {
if (compare(s, pi, si) && compareAt(s, pi, si, slen)) { if (compare(s, pi, si) && compareAt(s, pi, si, sLen)) {
return true; return true;
} }
si++; si++;
...@@ -222,7 +222,7 @@ public class CompareLike extends Condition { ...@@ -222,7 +222,7 @@ public class CompareLike extends Condition {
throw Message.getInternalError("type="+type); throw Message.getInternalError("type="+type);
} }
} }
return si==slen; return si==sLen;
} }
public boolean test(String pattern, String value, char escape) throws SQLException { public boolean test(String pattern, String value, char escape) throws SQLException {
...@@ -246,11 +246,11 @@ public class CompareLike extends Condition { ...@@ -246,11 +246,11 @@ public class CompareLike extends Condition {
int type; int type;
if (escape == c) { if (escape == c) {
if (i >= len - 1) { 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); c = p.charAt(++i);
if(c != '_' && c != '%' && c != escape) { 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; type = MATCH;
} else if (c == '%') { } else if (c == '%') {
......
...@@ -37,7 +37,7 @@ public class ConditionNot extends Condition { ...@@ -37,7 +37,7 @@ public class ConditionNot extends Condition {
} }
public Expression optimize(Session session) throws SQLException { 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); Expression expr = condition.optimize(session);
if(expr.isConstant()) { if(expr.isConstant()) {
Value v = expr.getValue(session); Value v = expr.getValue(session);
......
...@@ -213,7 +213,7 @@ public class ExpressionColumn extends Expression { ...@@ -213,7 +213,7 @@ public class ExpressionColumn extends Expression {
case ExpressionVisitor.INDEPENDENT: case ExpressionVisitor.INDEPENDENT:
return this.queryLevel < visitor.queryLevel; return this.queryLevel < visitor.queryLevel;
case ExpressionVisitor.EVALUATABLE: 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 // or if this columns belongs to a 'higher level' query and is therefore just a parameter
return evaluatable || visitor.queryLevel < this.queryLevel; return evaluatable || visitor.queryLevel < this.queryLevel;
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
......
...@@ -271,7 +271,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -271,7 +271,7 @@ public class Function extends Expression implements FunctionCall {
addFunctionNotConst("CURRVAL", CURRVAL, VARARGS, Value.LONG); addFunctionNotConst("CURRVAL", CURRVAL, VARARGS, Value.LONG);
addFunction("ARRAY_GET", ARRAY_GET, 2, Value.NULL); addFunction("ARRAY_GET", ARRAY_GET, 2, Value.NULL);
addFunction("CSVREAD", CSVREAD, VARARGS, Value.RESULT_SET, false, false); 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_FREE", MEMORY_FREE, 0, Value.INT);
addFunctionNotConst("MEMORY_USED", MEMORY_USED, 0, Value.INT); addFunctionNotConst("MEMORY_USED", MEMORY_USED, 0, Value.INT);
addFunctionNotConst("LOCK_MODE", LOCK_MODE, 0, Value.INT); addFunctionNotConst("LOCK_MODE", LOCK_MODE, 0, Value.INT);
...@@ -408,6 +408,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -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 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 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) { switch (info.type) {
case ABS: case ABS:
return v0.getSignum() > 0 ? v0 : v0.negate(); return v0.getSignum() > 0 ? v0 : v0.negate();
...@@ -548,7 +549,6 @@ public class Function extends Expression implements FunctionCall { ...@@ -548,7 +549,6 @@ public class Function extends Expression implements FunctionCall {
if (v1 == ValueNull.INSTANCE || v2 == ValueNull.INSTANCE) { if (v1 == ValueNull.INSTANCE || v2 == ValueNull.INSTANCE) {
return v1; return v1;
} }
Value v3 = args[3].getValue(session);
return ValueString.get(insert(v0.getString(), v1.getInt(), v2.getInt(), v3.getString())); return ValueString.get(insert(v0.getString(), v1.getInt(), v2.getInt(), v3.getString()));
} }
case LOWER: case LOWER:
...@@ -686,7 +686,6 @@ public class Function extends Expression implements FunctionCall { ...@@ -686,7 +686,6 @@ public class Function extends Expression implements FunctionCall {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
String locale = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString(); 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(); String tz = v3 == null ? null : v3 == ValueNull.INSTANCE ? null : v3.getString();
return ValueString.get(StringUtils.formatDateTime(v0.getTimestamp(), v1.getString(), locale, tz)); return ValueString.get(StringUtils.formatDateTime(v0.getTimestamp(), v1.getString(), locale, tz));
} }
...@@ -695,7 +694,6 @@ public class Function extends Expression implements FunctionCall { ...@@ -695,7 +694,6 @@ public class Function extends Expression implements FunctionCall {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
String locale = v2 == null ? null : v2 == ValueNull.INSTANCE ? null : v2.getString(); 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(); String tz = v3 == null ? null : v3 == ValueNull.INSTANCE ? null : v3.getString();
java.util.Date d = StringUtils.parseDateTime(v0.getString(), v1.getString(), locale, tz); java.util.Date d = StringUtils.parseDateTime(v0.getString(), v1.getString(), locale, tz);
return ValueTimestamp.getNoCopy(new Timestamp(d.getTime())); return ValueTimestamp.getNoCopy(new Timestamp(d.getTime()));
...@@ -707,7 +705,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -707,7 +705,7 @@ public class Function extends Expression implements FunctionCall {
case CURRENT_USER: case CURRENT_USER:
return ValueString.get(session.getUser().getName()); return ValueString.get(session.getUser().getName());
case IDENTITY: case IDENTITY:
return ValueLong.get(session.getLastIdentity()); return session.getLastIdentity();
case AUTOCOMMIT: case AUTOCOMMIT:
return ValueBoolean.get(session.getAutoCommit()); return ValueBoolean.get(session.getAutoCommit());
case READONLY: case READONLY:
...@@ -740,15 +738,27 @@ public class Function extends Expression implements FunctionCall { ...@@ -740,15 +738,27 @@ public class Function extends Expression implements FunctionCall {
case CSVREAD: { case CSVREAD: {
String fileName = v0.getString(); String fileName = v0.getString();
String columnList = v1 == null ? null : v1.getString(); String columnList = v1 == null ? null : v1.getString();
String[] columns = StringUtils.arraySplit(columnList, ',', true);
String charset = v2 == null ? null : v2.getString(); 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; return vr;
} }
case CSVWRITE: { case CSVWRITE: {
Connection conn = session.createConnection(false); Connection conn = session.createConnection(false);
String charset = v2 == null ? null : v2.getString(); 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; return ValueNull.INSTANCE;
} }
case MEMORY_FREE: case MEMORY_FREE:
...@@ -1386,9 +1396,16 @@ public class Function extends Expression implements FunctionCall { ...@@ -1386,9 +1396,16 @@ public class Function extends Expression implements FunctionCall {
throw Message.getSQLException(Message.PARAMETER_NOT_SET_1, "fileName"); throw Message.getSQLException(Message.PARAMETER_NOT_SET_1, "fileName");
} }
String columnList = args.length < 2 ? null : args[1].getValue(session).getString(); 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(); 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); ValueResultSet vr = ValueResultSet.getCopy(rs, 0);
return vr; return vr;
} }
......
...@@ -25,7 +25,7 @@ public class SequenceValue extends Expression { ...@@ -25,7 +25,7 @@ public class SequenceValue extends Expression {
public Value getValue(Session session) throws SQLException { public Value getValue(Session session) throws SQLException {
long value = sequence.getNext(); long value = sequence.getNext();
session.setLastIdentity(value); session.setLastIdentity(ValueLong.get(value));
return ValueLong.get(value); return ValueLong.get(value);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论