提交 e83c133c authored 作者: Owner's avatar Owner

Merged latest from master

...@@ -1991,7 +1991,7 @@ The following options are supported: ...@@ -1991,7 +1991,7 @@ The following options are supported:
""fieldDelimiter"" (a double quote by default), ""fieldDelimiter"" (a double quote by default),
""fieldSeparator"" (a comma by default)), ""fieldSeparator"" (a comma by default),
""lineComment"" (disabled by default), ""lineComment"" (disabled by default),
......
...@@ -49,7 +49,7 @@ http://www.h2database.com/html/roadmap.html ...@@ -49,7 +49,7 @@ http://www.h2database.com/html/roadmap.html
<p> <p>
The development of H2 was started in May 2004, The development of H2 was started in May 2004,
but it was first published on December 14th 2005. but it was first published on December 14th 2005.
The main author of H2, Thomas Mueller, is also the original developer of Hypersonic SQL. The original author of H2, Thomas Mueller, is also the original developer of Hypersonic SQL.
In 2001, he joined PointBase Inc. where he wrote PointBase Micro, a commercial Java SQL database. In 2001, he joined PointBase Inc. where he wrote PointBase Micro, a commercial Java SQL database.
At that point, he had to discontinue Hypersonic SQL. The HSQLDB Group was formed At that point, he had to discontinue Hypersonic SQL. The HSQLDB Group was formed
to continued to work on the Hypersonic SQL codebase. to continued to work on the Hypersonic SQL codebase.
...@@ -90,8 +90,12 @@ Java implementations (such as Swing) are not used, or only used for optional fea ...@@ -90,8 +90,12 @@ Java implementations (such as Swing) are not used, or only used for optional fea
<h2 id="supporters">Supporters</h2> <h2 id="supporters">Supporters</h2>
<p> <p>
Many thanks for those who reported bugs, gave valuable feedback, Many thanks for those who reported bugs, gave valuable feedback,
spread the word, and translated this project. Also many thanks to the donors. spread the word, and translated this project.
</p>
<p>
Also many thanks to the donors.
To become a donor, use PayPal (at the very bottom of the main web page). To become a donor, use PayPal (at the very bottom of the main web page).
Donators are:
</p> </p>
<ul> <ul>
<li>Martin Wildam, Austria <li>Martin Wildam, Austria
...@@ -106,6 +110,7 @@ To become a donor, use PayPal (at the very bottom of the main web page). ...@@ -106,6 +110,7 @@ To become a donor, use PayPal (at the very bottom of the main web page).
</li><li><a href="http://lumber-mill.co.jp">Lumber-mill, Inc., Japan</a> </li><li><a href="http://lumber-mill.co.jp">Lumber-mill, Inc., Japan</a>
</li><li><a href="http://www.stockmarketeye.com">StockMarketEye, USA</a> </li><li><a href="http://www.stockmarketeye.com">StockMarketEye, USA</a>
</li><li><a href="http://www.eckenfelder.de">Eckenfelder GmbH &amp; Co.KG, Germany</a> </li><li><a href="http://www.eckenfelder.de">Eckenfelder GmbH &amp; Co.KG, Germany</a>
</li><li>Jun Iyama, Japan
</li><li>Steven Branda, USA </li><li>Steven Branda, USA
</li><li>Anthony Goubard, Netherlands </li><li>Anthony Goubard, Netherlands
</li><li>Richard Hickey, USA </li><li>Richard Hickey, USA
...@@ -114,7 +119,6 @@ To become a donor, use PayPal (at the very bottom of the main web page). ...@@ -114,7 +119,6 @@ To become a donor, use PayPal (at the very bottom of the main web page).
</li><li>Donald Bleyl, USA </li><li>Donald Bleyl, USA
</li><li>Frank Berger, Germany </li><li>Frank Berger, Germany
</li><li>Florent Ramiere, France </li><li>Florent Ramiere, France
</li><li>Jun Iyama, Japan
</li><li>Antonio Casqueiro, Portugal </li><li>Antonio Casqueiro, Portugal
</li><li>Oliver Computing LLC, USA </li><li>Oliver Computing LLC, USA
</li><li>Harpal Grover Consulting Inc., USA </li><li>Harpal Grover Consulting Inc., USA
...@@ -134,7 +138,6 @@ To become a donor, use PayPal (at the very bottom of the main web page). ...@@ -134,7 +138,6 @@ To become a donor, use PayPal (at the very bottom of the main web page).
</li><li>Gustav Trede, Sweden </li><li>Gustav Trede, Sweden
</li><li>Joonas Pulakka, Finland </li><li>Joonas Pulakka, Finland
</li><li>Bjorn Darri Sigurdsson, Iceland </li><li>Bjorn Darri Sigurdsson, Iceland
</li><li>Iyama Jun, Japan
</li><li>Gray Watson, USA </li><li>Gray Watson, USA
</li><li>Erik Dick, Germany </li><li>Erik Dick, Germany
</li><li>Pengxiang Shao, China </li><li>Pengxiang Shao, China
...@@ -166,7 +169,13 @@ To become a donor, use PayPal (at the very bottom of the main web page). ...@@ -166,7 +169,13 @@ To become a donor, use PayPal (at the very bottom of the main web page).
</li><li>Cristan Meijer, Netherlands </li><li>Cristan Meijer, Netherlands
</li><li>Adam McMahon, USA </li><li>Adam McMahon, USA
</li><li>F&aacute;bio Gomes Lisboa Gomes, Brasil </li><li>F&aacute;bio Gomes Lisboa Gomes, Brasil
</li><li><a href="http://tao.works">Sam Blume, Switzerland</a> </li><li>Lyderic Landry, England
</li><li>Mederp, Morocco
</li><li>Joaquim Golay, Switzerland
</li><li>Clemens Quoss, Germany
</li><li>Kervin Pierre, USA
</li><li>Jake Bellotti, Australia
</li><li>Arun Chittanoor, USA
</li></ul> </li></ul>
<!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html> <!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html>
......
...@@ -670,6 +670,14 @@ Tune Backup</a><br /> ...@@ -670,6 +670,14 @@ Tune Backup</a><br />
Easy-to-use backup solution for your iTunes library. Easy-to-use backup solution for your iTunes library.
</p> </p>
<p><a href="http://www.timewriter.com">
TimeWriter</a><br />
TimeWriter is a very flexible program for time administration / time tracking.
The older versions used dBase tables.
The new version 5 is completely rewritten, now using the H2 database.
TimeWriter is delivered in Dutch and English.
</p>
<p><a href="http://www.weblica.ch"> <p><a href="http://www.weblica.ch">
weblica</a><br /> weblica</a><br />
Desktop CMS. Desktop CMS.
......
...@@ -5346,8 +5346,9 @@ public class Parser { ...@@ -5346,8 +5346,9 @@ public class Parser {
ArrayList<Expression> withExpressions = theQuery.getExpressions(); ArrayList<Expression> withExpressions = theQuery.getExpressions();
for (int i = 0; i < withExpressions.size(); ++i) { for (int i = 0; i < withExpressions.size(); ++i) {
Expression columnExp = withExpressions.get(i); Expression columnExp = withExpressions.get(i);
// use the passed in column name if supplied, otherwise use alias (if found) otherwise use column name // use the passed in column name if supplied, otherwise use alias
// derived from column expression // (if found) otherwise use column name derived from column
// expression
String columnName = columnNamer.getColumnName(columnExp,i,cols); String columnName = columnNamer.getColumnName(columnExp,i,cols);
columnTemplateList.add(new Column(columnName, columnTemplateList.add(new Column(columnName,
columnExp.getType())); columnExp.getType()));
......
...@@ -331,7 +331,8 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -331,7 +331,8 @@ public class AlterTableAddConstraint extends SchemaCommand {
} }
// all cols must be in the index key, the order doesn't matter and there must be no other fields in the index key // all cols must be in the index key, the order doesn't matter and there
// must be no other fields in the index key
private static boolean canUseUniqueIndex(Index idx, Table table, private static boolean canUseUniqueIndex(Index idx, Table table,
IndexColumn[] cols) { IndexColumn[] cols) {
if (idx.getTable() != table || !idx.getIndexType().isUnique()) { if (idx.getTable() != table || !idx.getIndexType().isUnique()) {
......
...@@ -274,12 +274,9 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -274,12 +274,9 @@ public class AlterTableAlterColumn extends SchemaCommand {
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, e, getSQL(), e.getMessage()); throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, e, getSQL(), e.getMessage());
} }
String tableName = table.getName(); String tableName = table.getName();
ArrayList<TableView> views = table.getViews(); ArrayList<TableView> dependentViews = new ArrayList<>(table.getDependentViews());
if (views != null) { for (TableView view : dependentViews) {
views = New.arrayList(views); table.removeDependentView(view);
for (TableView view : views) {
table.removeView(view);
}
} }
execute("DROP TABLE " + table.getSQL() + " IGNORE", true); execute("DROP TABLE " + table.getSQL() + " IGNORE", true);
db.renameSchemaObject(session, newTable, tableName); db.renameSchemaObject(session, newTable, tableName);
...@@ -306,13 +303,11 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -306,13 +303,11 @@ public class AlterTableAlterColumn extends SchemaCommand {
db.renameSchemaObject(session, so, name); db.renameSchemaObject(session, so, name);
} }
} }
if (views != null) { for (TableView view : dependentViews) {
for (TableView view : views) {
String sql = view.getCreateSQL(true, true); String sql = view.getCreateSQL(true, true);
execute(sql, true); execute(sql, true);
} }
} }
}
private Table cloneTableStructure(Table table, Column[] columns, Database db, private Table cloneTableStructure(Table table, Column[] columns, Database db,
String tempName, ArrayList<Column> newColumns) { String tempName, ArrayList<Column> newColumns) {
......
...@@ -133,23 +133,7 @@ public class Analyze extends DefineCommand { ...@@ -133,23 +133,7 @@ public class Analyze extends DefineCommand {
columns[j].setSelectivity(selectivity); columns[j].setSelectivity(selectivity);
} }
} }
if (manual) {
db.updateMeta(session, table); db.updateMeta(session, table);
} else {
Session sysSession = db.getSystemSession();
if (sysSession != session) {
// if the current session is the system session
// (which is the case if we are within a trigger)
// then we can't update the statistics because
// that would unlock all locked objects
synchronized (sysSession) {
// can't take the db lock yet, updateMeta needs to call
// lockMeta, and then it will take the db lock
db.updateMeta(sysSession, table);
sysSession.commit(true);
}
}
}
} }
public void setTop(int top) { public void setTop(int top) {
......
...@@ -9,7 +9,6 @@ import java.util.ArrayList; ...@@ -9,7 +9,6 @@ import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.command.dml.Query; import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
...@@ -99,12 +98,6 @@ public class CreateView extends SchemaCommand { ...@@ -99,12 +98,6 @@ public class CreateView extends SchemaCommand {
} }
querySQL = select.getPlanSQL(); querySQL = select.getPlanSQL();
} }
// The view creates a Prepared command object, which belongs to a
// session, so we pass the system session (not the current session) down.
// Why is the SYS session used here ? I think it might cause a problem...
Session sysSession = db.getSystemSession();
synchronized (sysSession) {
try {
Column[] columnTemplates = null; Column[] columnTemplates = null;
if (columnNames != null) { if (columnNames != null) {
columnTemplates = new Column[columnNames.length]; columnTemplates = new Column[columnNames.length];
...@@ -113,19 +106,11 @@ public class CreateView extends SchemaCommand { ...@@ -113,19 +106,11 @@ public class CreateView extends SchemaCommand {
} }
} }
if (view == null) { if (view == null) {
Schema schema = session.getDatabase().getSchema( view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false, false);
session.getCurrentSchemaName());
sysSession.setCurrentSchema(schema);
view = new TableView(getSchema(), id, viewName, querySQL, null,
columnTemplates, sysSession, false, false);
} else { } else {
view.replace(querySQL, columnTemplates, sysSession, false, force, false); view.replace(querySQL, columnTemplates, session, false, force, false);
view.setModified(); view.setModified();
} }
} finally {
sysSession.setCurrentSchema(db.getSchema(Constants.SCHEMA_MAIN));
}
}
if (comment != null) { if (comment != null) {
view.setComment(comment); view.setComment(comment);
} }
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
*/ */
package org.h2.command.ddl; package org.h2.command.ddl;
import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.constraint.ConstraintReferential; import org.h2.constraint.ConstraintReferential;
...@@ -74,10 +73,10 @@ public class DropTable extends SchemaCommand { ...@@ -74,10 +73,10 @@ public class DropTable extends SchemaCommand {
throw DbException.get(ErrorCode.CANNOT_DROP_TABLE_1, tableName); throw DbException.get(ErrorCode.CANNOT_DROP_TABLE_1, tableName);
} }
if (dropAction == ConstraintReferential.RESTRICT) { if (dropAction == ConstraintReferential.RESTRICT) {
ArrayList<TableView> views = table.getViews(); CopyOnWriteArrayList<TableView> dependentViews = table.getDependentViews();
if (views != null && views.size() > 0) { if (dependentViews != null && dependentViews.size() > 0) {
StatementBuilder buff = new StatementBuilder(); StatementBuilder buff = new StatementBuilder();
for (TableView v : views) { for (TableView v : dependentViews) {
buff.appendExceptFirst(", "); buff.appendExceptFirst(", ");
buff.append(v.getName()); buff.append(v.getName());
} }
......
...@@ -114,16 +114,7 @@ public class AlterSequence extends SchemaCommand { ...@@ -114,16 +114,7 @@ public class AlterSequence extends SchemaCommand {
Long inc = getLong(increment); Long inc = getLong(increment);
sequence.modify(startValue, min, max, inc); sequence.modify(startValue, min, max, inc);
} }
// need to use the system session, so that the update db.updateMeta(session, sequence);
// can be committed immediately - not committing it
// would keep other transactions from using the sequence
Session sysSession = db.getSystemSession();
synchronized (sysSession) {
synchronized (db) {
db.updateMeta(sysSession, sequence);
sysSession.commit(true);
}
}
return 0; return 0;
} }
......
...@@ -245,7 +245,8 @@ public class MergeUsing extends Prepared { ...@@ -245,7 +245,8 @@ public class MergeUsing extends Prepared {
// throw and exception if we have processed this _ROWID_ before... // throw and exception if we have processed this _ROWID_ before...
if (targetRowidsRemembered.containsKey(targetRowIdValue[0])) { if (targetRowidsRemembered.containsKey(targetRowIdValue[0])) {
throw DbException.get(ErrorCode.DUPLICATE_KEY_1, throw DbException.get(ErrorCode.DUPLICATE_KEY_1,
"Merge using ON column expression, duplicate _ROWID_ target record already updated, deleted or inserted:_ROWID_=" "Merge using ON column expression, " +
"duplicate _ROWID_ target record already updated, deleted or inserted:_ROWID_="
+ targetRowIdValue[0].toString() + ":in:" + targetRowIdValue[0].toString() + ":in:"
+ targetTableFilter.getTable() + targetTableFilter.getTable()
+ ":conflicting source row number:" + ":conflicting source row number:"
......
...@@ -472,7 +472,8 @@ public class Constants { ...@@ -472,7 +472,8 @@ public class Constants {
public static final String SUFFIX_TRACE_FILE = ".trace.db"; public static final String SUFFIX_TRACE_FILE = ".trace.db";
/** /**
* How often we check to see if we need to apply a throttling delay if SET THROTTLE has been used. * How often we check to see if we need to apply a throttling delay if SET
* THROTTLE has been used.
*/ */
public static final int THROTTLE_DELAY = 50; public static final int THROTTLE_DELAY = 50;
......
...@@ -974,6 +974,12 @@ public class Database implements DataHandler { ...@@ -974,6 +974,12 @@ public class Database implements DataHandler {
session.unlock(meta); session.unlock(meta);
} }
/**
* This method doesn't actually unlock the metadata table, all it does it
* reset the debugging flags.
*
* @param session the session
*/
public void unlockMetaDebug(Session session) { public void unlockMetaDebug(Session session) {
if (SysProperties.CHECK2) { if (SysProperties.CHECK2) {
if (metaLockDebugging.get() == session) { if (metaLockDebugging.get() == session) {
......
...@@ -376,7 +376,8 @@ public class Session extends SessionWithState { ...@@ -376,7 +376,8 @@ public class Session extends SessionWithState {
* @param table the table * @param table the table
*/ */
public void removeLocalTempTable(Table table) { public void removeLocalTempTable(Table table) {
// Exception thrown in org.h2.engine.Database.removeMeta if line below is missing with TestGeneralCommonTableQueries // Exception thrown in org.h2.engine.Database.removeMeta if line below
// is missing with TestGeneralCommonTableQueries
database.lockMeta(this); database.lockMeta(this);
modificationId++; modificationId++;
localTempTables.remove(table.getName()); localTempTables.remove(table.getName());
...@@ -678,6 +679,7 @@ public class Session extends SessionWithState { ...@@ -678,6 +679,7 @@ public class Session extends SessionWithState {
for (Table table : tablesToAnalyze) { for (Table table : tablesToAnalyze) {
Analyze.analyzeTable(this, table, rows, false); Analyze.analyzeTable(this, table, rows, false);
} }
database.unlockMeta(this); // analyze can lock the meta
} }
tablesToAnalyze = null; tablesToAnalyze = null;
} }
...@@ -984,7 +986,8 @@ public class Session extends SessionWithState { ...@@ -984,7 +986,8 @@ public class Session extends SessionWithState {
modificationId++; modificationId++;
table.setModified(); table.setModified();
it.remove(); it.remove();
// Exception thrown in org.h2.engine.Database.removeMeta if line below is missing with TestDeadlock // Exception thrown in org.h2.engine.Database.removeMeta
// if line below is missing with TestDeadlock
database.lockMeta(this); database.lockMeta(this);
table.removeChildrenAndResources(this); table.removeChildrenAndResources(this);
if (closeSession) { if (closeSession) {
......
...@@ -114,8 +114,7 @@ public class SessionRemote extends SessionWithState implements DataHandler { ...@@ -114,8 +114,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
throws IOException { throws IOException {
Socket socket = NetUtils.createSocket(server, Socket socket = NetUtils.createSocket(server,
Constants.DEFAULT_TCP_PORT, ci.isSSL()); Constants.DEFAULT_TCP_PORT, ci.isSSL());
Transfer trans = new Transfer(this); Transfer trans = new Transfer(this, socket);
trans.setSocket(socket);
trans.setSSL(ci.isSSL()); trans.setSSL(ci.isSSL());
trans.init(); trans.init();
trans.writeInt(Constants.TCP_PROTOCOL_VERSION_6); trans.writeInt(Constants.TCP_PROTOCOL_VERSION_6);
......
...@@ -1740,8 +1740,9 @@ public class JdbcConnection extends TraceObject ...@@ -1740,8 +1740,9 @@ public class JdbcConnection extends TraceObject
} }
checkClosed(); checkClosed();
// no change to property: Ignore call. This early exit fixes a problem with websphere liberty // no change to property: Ignore call. This early exit fixes a
// resetting the client info of a pooled connection to its initial values. // problem with websphere liberty resetting the client info of a
// pooled connection to its initial values.
if (Objects.equals(value, getClientInfo(name))) { if (Objects.equals(value, getClientInfo(name))) {
return; return;
} }
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
package org.h2.mvstore.db; package org.h2.mvstore.db;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
......
...@@ -32,7 +32,6 @@ public class Sequence extends SchemaObjectBase { ...@@ -32,7 +32,6 @@ public class Sequence extends SchemaObjectBase {
private long maxValue; private long maxValue;
private boolean cycle; private boolean cycle;
private boolean belongsToTable; private boolean belongsToTable;
private final Object flushSync = new Object();
private boolean writeWithMargin; private boolean writeWithMargin;
/** /**
...@@ -306,7 +305,6 @@ public class Sequence extends SchemaObjectBase { ...@@ -306,7 +305,6 @@ public class Sequence extends SchemaObjectBase {
} }
private void flushInternal(Session session) { private void flushInternal(Session session) {
synchronized (flushSync) {
final boolean metaWasLocked = database.lockMeta(session); final boolean metaWasLocked = database.lockMeta(session);
// just for this case, use the value with the margin // just for this case, use the value with the margin
try { try {
...@@ -319,7 +317,6 @@ public class Sequence extends SchemaObjectBase { ...@@ -319,7 +317,6 @@ public class Sequence extends SchemaObjectBase {
database.unlockMeta(session); database.unlockMeta(session);
} }
} }
}
/** /**
* Flush the current value to disk and close this object. * Flush the current value to disk and close this object.
......
...@@ -62,8 +62,7 @@ public class TcpServerThread implements Runnable { ...@@ -62,8 +62,7 @@ public class TcpServerThread implements Runnable {
TcpServerThread(Socket socket, TcpServer server, int id) { TcpServerThread(Socket socket, TcpServer server, int id) {
this.server = server; this.server = server;
this.threadId = id; this.threadId = id;
transfer = new Transfer(null); transfer = new Transfer(null, socket);
transfer.setSocket(socket);
} }
private void trace(String s) { private void trace(String s) {
...@@ -78,6 +77,11 @@ public class TcpServerThread implements Runnable { ...@@ -78,6 +77,11 @@ public class TcpServerThread implements Runnable {
// TODO server: should support a list of allowed databases // TODO server: should support a list of allowed databases
// and a list of allowed clients // and a list of allowed clients
try { try {
Socket socket = transfer.getSocket();
if (socket == null) {
// the transfer is already closed, prevent NPE in TcpServer#allow(Socket)
return;
}
if (!server.allow(transfer.getSocket())) { if (!server.allow(transfer.getSocket())) {
throw DbException.get(ErrorCode.REMOTE_CONNECTION_NOT_ALLOWED); throw DbException.get(ErrorCode.REMOTE_CONNECTION_NOT_ALLOWED);
} }
......
...@@ -234,8 +234,7 @@ public class FileLock implements Runnable { ...@@ -234,8 +234,7 @@ public class FileLock implements Runnable {
try { try {
Socket socket = NetUtils.createSocket(server, Socket socket = NetUtils.createSocket(server,
Constants.DEFAULT_TCP_PORT, false); Constants.DEFAULT_TCP_PORT, false);
Transfer transfer = new Transfer(null); Transfer transfer = new Transfer(null, socket);
transfer.setSocket(socket);
transfer.init(); transfer.init();
transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_6); transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_6);
transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_16); transfer.writeInt(Constants.TCP_PROTOCOL_VERSION_16);
...@@ -523,10 +522,15 @@ public class FileLock implements Runnable { ...@@ -523,10 +522,15 @@ public class FileLock implements Runnable {
trace.debug(e, "watchdog"); trace.debug(e, "watchdog");
} }
} }
while (serverSocket != null) { while (true) {
// take a copy so we don't get an NPE between checking it and using it
ServerSocket local = serverSocket;
if (local == null) {
break;
}
try { try {
trace.debug("watchdog accept"); trace.debug("watchdog accept");
Socket s = serverSocket.accept(); Socket s = local.accept();
s.close(); s.close();
} catch (Exception e) { } catch (Exception e) {
trace.debug(e, "watchdog"); trace.debug(e, "watchdog");
......
...@@ -10,6 +10,7 @@ import java.util.Arrays; ...@@ -10,6 +10,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.constraint.Constraint; import org.h2.constraint.Constraint;
...@@ -77,7 +78,10 @@ public abstract class Table extends SchemaObjectBase { ...@@ -77,7 +78,10 @@ public abstract class Table extends SchemaObjectBase {
private ArrayList<TriggerObject> triggers; private ArrayList<TriggerObject> triggers;
private ArrayList<Constraint> constraints; private ArrayList<Constraint> constraints;
private ArrayList<Sequence> sequences; private ArrayList<Sequence> sequences;
private ArrayList<TableView> views; // remember which views are using this object /**
* views that depend on this table
*/
private final CopyOnWriteArrayList<TableView> dependentViews = new CopyOnWriteArrayList<>();
private ArrayList<TableSynonym> synonyms; private ArrayList<TableSynonym> synonyms;
private boolean checkForeignKeyConstraints = true; private boolean checkForeignKeyConstraints = true;
private boolean onCommitDrop, onCommitTruncate; private boolean onCommitDrop, onCommitTruncate;
...@@ -339,6 +343,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -339,6 +343,7 @@ public abstract class Table extends SchemaObjectBase {
return null; return null;
} }
@Override
public String getCreateSQLForCopy(Table table, String quotedName) { public String getCreateSQLForCopy(Table table, String quotedName) {
throw DbException.throwInternalError(toString()); throw DbException.throwInternalError(toString());
} }
...@@ -398,9 +403,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -398,9 +403,7 @@ public abstract class Table extends SchemaObjectBase {
if (sequences != null) { if (sequences != null) {
children.addAll(sequences); children.addAll(sequences);
} }
if (views != null) { children.addAll(dependentViews);
children.addAll(views);
}
if (synonyms != null) { if (synonyms != null) {
children.addAll(synonyms); children.addAll(synonyms);
} }
...@@ -518,15 +521,15 @@ public abstract class Table extends SchemaObjectBase { ...@@ -518,15 +521,15 @@ public abstract class Table extends SchemaObjectBase {
} }
} }
public ArrayList<TableView> getViews() { public CopyOnWriteArrayList<TableView> getDependentViews() {
return views; return dependentViews;
} }
@Override @Override
public void removeChildrenAndResources(Session session) { public void removeChildrenAndResources(Session session) {
while (views != null && views.size() > 0) { while (dependentViews.size() > 0) {
TableView view = views.get(0); TableView view = dependentViews.get(0);
views.remove(0); dependentViews.remove(0);
database.removeSchemaObject(session, view); database.removeSchemaObject(session, view);
} }
while (synonyms != null && synonyms.size() > 0) { while (synonyms != null && synonyms.size() > 0) {
...@@ -810,10 +813,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -810,10 +813,7 @@ public abstract class Table extends SchemaObjectBase {
private static void remove(ArrayList<? extends DbObject> list, DbObject obj) { private static void remove(ArrayList<? extends DbObject> list, DbObject obj) {
if (list != null) { if (list != null) {
int i = list.indexOf(obj); list.remove(obj);
if (i >= 0) {
list.remove(i);
}
} }
} }
...@@ -839,8 +839,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -839,8 +839,8 @@ public abstract class Table extends SchemaObjectBase {
* *
* @param view the view to remove * @param view the view to remove
*/ */
public void removeView(TableView view) { public void removeDependentView(TableView view) {
remove(views, view); dependentViews.remove(view);
} }
/** /**
...@@ -884,8 +884,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -884,8 +884,8 @@ public abstract class Table extends SchemaObjectBase {
* *
* @param view the view to add * @param view the view to add
*/ */
public void addView(TableView view) { public void addDependentView(TableView view) {
views = add(views, view); dependentViews.add(view);
} }
/** /**
......
...@@ -58,7 +58,7 @@ public class TableView extends Table { ...@@ -58,7 +58,7 @@ public class TableView extends Table {
private Query topQuery; private Query topQuery;
private ResultInterface recursiveResult; private ResultInterface recursiveResult;
private boolean isRecursiveQueryDetected; private boolean isRecursiveQueryDetected;
private Session session; // private Session session;
public TableView(Schema schema, int id, String name, String querySQL, public TableView(Schema schema, int id, String name, String querySQL,
ArrayList<Parameter> params, Column[] columnTemplates, Session session, ArrayList<Parameter> params, Column[] columnTemplates, Session session,
...@@ -99,7 +99,7 @@ public class TableView extends Table { ...@@ -99,7 +99,7 @@ public class TableView extends Table {
this.columnTemplates = columnTemplates; this.columnTemplates = columnTemplates;
this.recursive = recursive; this.recursive = recursive;
this.isRecursiveQueryDetected = false; this.isRecursiveQueryDetected = false;
this.session = session; //this.session = session;
index = new ViewIndex(this, querySQL, params, recursive); index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session, literalsChecked); initColumnsAndTables(session, literalsChecked);
} }
...@@ -136,19 +136,14 @@ public class TableView extends Table { ...@@ -136,19 +136,14 @@ public class TableView extends Table {
return e; return e;
} }
} }
ArrayList<TableView> views = getViews(); ArrayList<TableView> dependentViews = new ArrayList<>(getDependentViews());
if (views != null) {
views = New.arrayList(views);
}
initColumnsAndTables(session, false); initColumnsAndTables(session, false);
if (views != null) { for (TableView v : dependentViews) {
for (TableView v : views) {
DbException e = v.recompile(session, force, false); DbException e = v.recompile(session, force, false);
if (e != null && !force) { if (e != null && !force) {
return e; return e;
} }
} }
}
if (clearIndexCache) { if (clearIndexCache) {
clearIndexCaches(database); clearIndexCaches(database);
} }
...@@ -157,7 +152,7 @@ public class TableView extends Table { ...@@ -157,7 +152,7 @@ public class TableView extends Table {
private void initColumnsAndTables(Session session, boolean literalsChecked) { private void initColumnsAndTables(Session session, boolean literalsChecked) {
Column[] cols; Column[] cols;
removeViewFromTables(); removeDependentViewFromTables();
try { try {
Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked); Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked);
this.querySQL = compiledQuery.getPlanSQL(); this.querySQL = compiledQuery.getPlanSQL();
...@@ -232,7 +227,7 @@ public class TableView extends Table { ...@@ -232,7 +227,7 @@ public class TableView extends Table {
} }
setColumns(cols); setColumns(cols);
if (getId() != 0) { if (getId() != 0) {
addViewToTables(); addDependentViewToTables();
} }
} }
...@@ -423,7 +418,7 @@ public class TableView extends Table { ...@@ -423,7 +418,7 @@ public class TableView extends Table {
@Override @Override
public void removeChildrenAndResources(Session session) { public void removeChildrenAndResources(Session session) {
removeViewFromTables(); removeDependentViewFromTables();
super.removeChildrenAndResources(session); super.removeChildrenAndResources(session);
database.removeMeta(session, getId()); database.removeMeta(session, getId());
querySQL = null; querySQL = null;
...@@ -507,18 +502,18 @@ public class TableView extends Table { ...@@ -507,18 +502,18 @@ public class TableView extends Table {
return null; return null;
} }
private void removeViewFromTables() { private void removeDependentViewFromTables() {
if (tables != null) { if (tables != null) {
for (Table t : tables) { for (Table t : tables) {
t.removeView(this); t.removeDependentView(this);
} }
tables.clear(); tables.clear();
} }
} }
private void addViewToTables() { private void addDependentViewToTables() {
for (Table t : tables) { for (Table t : tables) {
t.addView(this); t.addDependentView(this);
} }
} }
...@@ -696,17 +691,17 @@ public class TableView extends Table { ...@@ -696,17 +691,17 @@ public class TableView extends Table {
return true; return true;
} }
@Override // @Override
public void removeView(TableView view){ // public void removeView(TableView view){
super.removeView(view); // super.removeView(view);
// if this is a table expression and the last view to use it is // // if this is a table expression and the last view to use it is
// being dropped - then remove itself from the schema // // being dropped - then remove itself from the schema
if(isTableExpression() && getViews()!=null){ // if(isTableExpression() && getViews()!=null){
// check if any database objects are left using this view // // check if any database objects are left using this view
if(getViews().size()==0 && !isBeingDropped()){ // if(getViews().size()==0 && !isBeingDropped()){
System.out.println("Detected unused CTE: Trying to remove="+this.getName()+",session="+session.toString()+",sessionId="+session.getId()); // System.out.println("Detected unused CTE: Trying to remove="+this.getName()+",session="+session.toString()+",sessionId="+session.getId());
session.getDatabase().removeSchemaObject(session,this); // session.getDatabase().removeSchemaObject(session,this);
} // }
} // }
} // }
} }
...@@ -29,6 +29,7 @@ public class ColumnNamer { ...@@ -29,6 +29,7 @@ public class ColumnNamer {
} }
} }
} }
/** /**
* Create a standardized column name that isn't null and doesn't have a CR/LF in it. * Create a standardized column name that isn't null and doesn't have a CR/LF in it.
* @param expr the column expression * @param expr the column expression
...@@ -37,6 +38,7 @@ public class ColumnNamer { ...@@ -37,6 +38,7 @@ public class ColumnNamer {
public String getColumnName(Expression expr, int indexOfColumn) { public String getColumnName(Expression expr, int indexOfColumn) {
return getColumnName(expr,indexOfColumn,(String) null); return getColumnName(expr,indexOfColumn,(String) null);
} }
/** /**
* Create a standardized column name that isn't null and doesn't have a CR/LF in it. * Create a standardized column name that isn't null and doesn't have a CR/LF in it.
* @param columnExp the column expression * @param columnExp the column expression
...@@ -44,9 +46,9 @@ public class ColumnNamer { ...@@ -44,9 +46,9 @@ public class ColumnNamer {
* @param columnNameOverides array of overriding column names * @param columnNameOverides array of overriding column names
* @return the new column name * @return the new column name
*/ */
public String getColumnName(Expression columnExp, int indexOfColumn, String[] columnNameOverides){ public String getColumnName(Expression columnExp, int indexOfColumn, String[] columnNameOverides) {
String columnNameOverride = null; String columnNameOverride = null;
if (columnNameOverides != null && columnNameOverides.length > indexOfColumn){ if (columnNameOverides != null && columnNameOverides.length > indexOfColumn) {
columnNameOverride = columnNameOverides[indexOfColumn]; columnNameOverride = columnNameOverides[indexOfColumn];
} }
return getColumnName(columnExp, indexOfColumn, columnNameOverride); return getColumnName(columnExp, indexOfColumn, columnNameOverride);
...@@ -72,40 +74,43 @@ public class ColumnNamer { ...@@ -72,40 +74,43 @@ public class ColumnNamer {
} }
} }
// try a name from the column alias // try a name from the column alias
if (columnName==null && columnExp.getAlias()!=null && !DEFAULT_COLUMN_NAME.equals(columnExp.getAlias())){ if (columnName==null && columnExp.getAlias()!=null &&
!DEFAULT_COLUMN_NAME.equals(columnExp.getAlias())) {
columnName = columnExp.getAlias(); columnName = columnExp.getAlias();
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = fixColumnName(columnName); columnName = fixColumnName(columnName);
} }
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = null; columnName = null;
} }
} }
// try a name derived from the column expression SQL // try a name derived from the column expression SQL
if (columnName==null && columnExp.getColumnName()!=null && !DEFAULT_COLUMN_NAME.equals(columnExp.getColumnName())){ if (columnName == null && columnExp.getColumnName() != null &&
!DEFAULT_COLUMN_NAME.equals(columnExp.getColumnName())) {
columnName = columnExp.getColumnName(); columnName = columnExp.getColumnName();
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = fixColumnName(columnName); columnName = fixColumnName(columnName);
} }
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = null; columnName = null;
} }
} }
// try a name derived from the column expression plan SQL // try a name derived from the column expression plan SQL
if (columnName==null && columnExp.getSQL()!=null && !DEFAULT_COLUMN_NAME.equals(columnExp.getSQL())){ if (columnName == null && columnExp.getSQL() != null &&
!DEFAULT_COLUMN_NAME.equals(columnExp.getSQL())) {
columnName = columnExp.getSQL(); columnName = columnExp.getSQL();
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = fixColumnName(columnName); columnName = fixColumnName(columnName);
} }
if(!isAllowableColumnName(columnName)){ if (!isAllowableColumnName(columnName)) {
columnName = null; columnName = null;
} }
} }
// go with a innocuous default name pattern // go with a innocuous default name pattern
if (columnName==null){ if (columnName == null) {
columnName = configuration.getDefaultColumnNamePattern().replace("$$", ""+(indexOfColumn+1)); columnName = configuration.getDefaultColumnNamePattern().replace("$$", "" + (indexOfColumn + 1));
} }
if(existingColumnNames.contains(columnName) && configuration.isGenerateUniqueColumnNames()){ if (existingColumnNames.contains(columnName) && configuration.isGenerateUniqueColumnNames()) {
columnName = generateUniqueName(columnName); columnName = generateUniqueName(columnName);
} }
existingColumnNames.add(columnName); existingColumnNames.add(columnName);
...@@ -115,11 +120,11 @@ public class ColumnNamer { ...@@ -115,11 +120,11 @@ public class ColumnNamer {
private String generateUniqueName(String columnName) { private String generateUniqueName(String columnName) {
String newColumnName = columnName; String newColumnName = columnName;
int loopCount = 2; int loopCount = 2;
while(existingColumnNames.contains(newColumnName)){ while (existingColumnNames.contains(newColumnName)) {
String loopCountString = "_"+loopCount; String loopCountString = "_"+loopCount;
newColumnName = columnName.substring(0,Math.min(columnName.length(), configuration.getMaxIdentiferLength()-loopCountString.length()))+loopCountString; newColumnName = columnName.substring(0,
Math.min(columnName.length(), configuration.getMaxIdentiferLength() - loopCountString.length()))
+ loopCountString;
loopCount++; loopCount++;
} }
return newColumnName; return newColumnName;
...@@ -132,11 +137,11 @@ public class ColumnNamer { ...@@ -132,11 +137,11 @@ public class ColumnNamer {
return false; return false;
} }
// check size limits // check size limits
if (proposedName.length() > configuration.getMaxIdentiferLength() || proposedName.length()==0){ if (proposedName.length() > configuration.getMaxIdentiferLength() || proposedName.length() == 0) {
return false; return false;
} }
Matcher match = configuration.getCompiledRegularExpressionMatchAllowed().matcher(proposedName); Matcher match = configuration.getCompiledRegularExpressionMatchAllowed().matcher(proposedName);
if(!match.matches()){ if (!match.matches()) {
return false; return false;
} }
return true; return true;
......
...@@ -23,7 +23,8 @@ public class ColumnNamerConfiguration { ...@@ -23,7 +23,8 @@ public class ColumnNamerConfiguration {
private Pattern compiledRegularExpressionMatchDisallowed; private Pattern compiledRegularExpressionMatchDisallowed;
public ColumnNamerConfiguration(int maxIdentiferLength, String regularExpressionMatchAllowed, public ColumnNamerConfiguration(int maxIdentiferLength, String regularExpressionMatchAllowed,
String regularExpressionMatchDisallowed, String defaultColumnNamePattern, boolean generateUniqueColumnNames) { String regularExpressionMatchDisallowed, String defaultColumnNamePattern,
boolean generateUniqueColumnNames) {
this.maxIdentiferLength = maxIdentiferLength; this.maxIdentiferLength = maxIdentiferLength;
this.regularExpressionMatchAllowed = regularExpressionMatchAllowed; this.regularExpressionMatchAllowed = regularExpressionMatchAllowed;
...@@ -41,8 +42,9 @@ public class ColumnNamerConfiguration { ...@@ -41,8 +42,9 @@ public class ColumnNamerConfiguration {
public void setMaxIdentiferLength(int maxIdentiferLength) { public void setMaxIdentiferLength(int maxIdentiferLength) {
this.maxIdentiferLength = Math.max(30,maxIdentiferLength); this.maxIdentiferLength = Math.max(30,maxIdentiferLength);
if(maxIdentiferLength!=getMaxIdentiferLength()){ if (maxIdentiferLength != getMaxIdentiferLength()) {
throw DbException.getInvalidValueException("Illegal value (<30) in SET COLUMN_NAME_RULES","MAX_IDENTIFIER_LENGTH="+maxIdentiferLength); throw DbException.getInvalidValueException("Illegal value (<30) in SET COLUMN_NAME_RULES",
"MAX_IDENTIFIER_LENGTH=" + maxIdentiferLength);
} }
} }
...@@ -88,25 +90,28 @@ public class ColumnNamerConfiguration { ...@@ -88,25 +90,28 @@ public class ColumnNamerConfiguration {
public void configure(String stringValue) { public void configure(String stringValue) {
try{ try{
if(stringValue.equalsIgnoreCase(DEFAULT_COMMAND)){ if (stringValue.equalsIgnoreCase(DEFAULT_COMMAND)) {
configure(REGULAR); configure(REGULAR);
} else if(stringValue.startsWith(EMULATE_COMMAND)){ } else if (stringValue.startsWith(EMULATE_COMMAND)) {
configure(ModeEnum.valueOf(unquoteString(stringValue.substring(EMULATE_COMMAND.length())))); configure(ModeEnum.valueOf(
} else if(stringValue.startsWith(MAX_IDENTIFIER_LENGTH)){ unquoteString(stringValue.substring(EMULATE_COMMAND.length()))));
} else if (stringValue.startsWith(MAX_IDENTIFIER_LENGTH)) {
int maxLength = Integer.parseInt(stringValue.substring(MAX_IDENTIFIER_LENGTH.length())); int maxLength = Integer.parseInt(stringValue.substring(MAX_IDENTIFIER_LENGTH.length()));
setMaxIdentiferLength(maxLength); setMaxIdentiferLength(maxLength);
} else if(stringValue.startsWith(GENERATE_UNIQUE_COLUMN_NAMES)){ } else if (stringValue.startsWith(GENERATE_UNIQUE_COLUMN_NAMES)) {
setGenerateUniqueColumnNames(Integer.parseInt(stringValue.substring(GENERATE_UNIQUE_COLUMN_NAMES.length()))==1); setGenerateUniqueColumnNames(
} else if(stringValue.startsWith(DEFAULT_COLUMN_NAME_PATTERN)){ Integer.parseInt(stringValue.substring(GENERATE_UNIQUE_COLUMN_NAMES.length())) == 1);
setDefaultColumnNamePattern(unquoteString(stringValue.substring(DEFAULT_COLUMN_NAME_PATTERN.length()))); } else if (stringValue.startsWith(DEFAULT_COLUMN_NAME_PATTERN)) {
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_ALLOWED)){ setDefaultColumnNamePattern(
setRegularExpressionMatchAllowed(unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_ALLOWED.length()))); unquoteString(stringValue.substring(DEFAULT_COLUMN_NAME_PATTERN.length())));
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_DISALLOWED)){ } else if (stringValue.startsWith(REGULAR_EXPRESSION_MATCH_ALLOWED)) {
setRegularExpressionMatchDisallowed(unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_DISALLOWED.length()))); setRegularExpressionMatchAllowed(
} unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_ALLOWED.length())));
else } else if (stringValue.startsWith(REGULAR_EXPRESSION_MATCH_DISALLOWED)) {
{ setRegularExpressionMatchDisallowed(
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES: unknown id:"+stringValue, unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_DISALLOWED.length())));
} else {
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES: unknown id:" + stringValue,
stringValue); stringValue);
} }
...@@ -157,7 +162,8 @@ public class ColumnNamerConfiguration { ...@@ -157,7 +162,8 @@ public class ColumnNamerConfiguration {
switch(modeEnum){ switch(modeEnum){
case Oracle: case Oracle:
// Nonquoted identifiers can contain only alphanumeric characters // Nonquoted identifiers can contain only alphanumeric characters
// from your database character set and the underscore (_), dollar sign ($), and pound sign (#). // from your database character set and the underscore (_), dollar
// sign ($), and pound sign (#).
setMaxIdentiferLength(128); setMaxIdentiferLength(128);
setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_\\$#]+\"?"); setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_\\$#]+\"?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"\\$#]"); setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"\\$#]");
......
...@@ -58,17 +58,9 @@ public class Transfer { ...@@ -58,17 +58,9 @@ public class Transfer {
* *
* @param session the session * @param session the session
*/ */
public Transfer(SessionInterface session) { public Transfer(SessionInterface session, Socket s) {
this.session = session; this.session = session;
} this.socket = s;
/**
* Set the socket this object uses.
*
* @param s the socket
*/
public void setSocket(Socket s) {
socket = s;
} }
/** /**
...@@ -764,8 +756,7 @@ public class Transfer { ...@@ -764,8 +756,7 @@ public class Transfer {
InetAddress address = socket.getInetAddress(); InetAddress address = socket.getInetAddress();
int port = socket.getPort(); int port = socket.getPort();
Socket s2 = NetUtils.createSocket(address, port, ssl); Socket s2 = NetUtils.createSocket(address, port, ssl);
Transfer trans = new Transfer(null); Transfer trans = new Transfer(null, s2);
trans.setSocket(s2);
trans.setSSL(ssl); trans.setSSL(ssl);
return trans; return trans;
} }
......
...@@ -55,10 +55,12 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -55,10 +55,12 @@ public class TestCompatibilityOracle extends TestBase {
stat.execute("insert into T values(1)"); stat.execute("insert into T values(1)");
stat.execute("drop table T"); stat.execute("drop table T");
// can set NULL // can set NULL
stat.execute("create table T (C int not null disable)"); // can set NULL even with 'not null syntax' (oracle) // can set NULL even with 'not null syntax' (oracle)
stat.execute("create table T (C int not null disable)");
stat.execute("insert into T values(null)"); stat.execute("insert into T values(null)");
stat.execute("drop table T"); stat.execute("drop table T");
stat.execute("create table T (C int not null enable novalidate)"); // can set NULL even with 'not null syntax' (oracle) // can set NULL even with 'not null syntax' (oracle)
stat.execute("create table T (C int not null enable novalidate)");
stat.execute("insert into T values(null)"); stat.execute("insert into T values(null)");
stat.execute("drop table T"); stat.execute("drop table T");
...@@ -78,9 +80,11 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -78,9 +80,11 @@ public class TestCompatibilityOracle extends TestBase {
stat.execute("alter table T modify C null enable"); stat.execute("alter table T modify C null enable");
stat.execute("alter table T modify C null enable validate"); stat.execute("alter table T modify C null enable validate");
stat.execute("insert into T values(null)"); stat.execute("insert into T values(null)");
stat.execute("alter table T modify C not null disable"); // can set NULL even with 'not null syntax' (oracle) // can set NULL even with 'not null syntax' (oracle)
stat.execute("alter table T modify C not null disable");
stat.execute("insert into T values(null)"); stat.execute("insert into T values(null)");
stat.execute("alter table T modify C not null enable novalidate"); // can set NULL even with 'not null syntax' (oracle) // can set NULL even with 'not null syntax' (oracle)
stat.execute("alter table T modify C not null enable novalidate");
stat.execute("insert into T values(null)"); stat.execute("insert into T values(null)");
stat.execute("drop table T"); stat.execute("drop table T");
......
...@@ -29,20 +29,20 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -29,20 +29,20 @@ public class TestGeneralCommonTableQueries extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
// testSimpleSelect(); testSimpleSelect();
// testImpliedColumnNames(); testImpliedColumnNames();
// testChainedQuery(); testChainedQuery();
// testParameterizedQuery(); testParameterizedQuery();
// testNumberedParameterizedQuery(); testNumberedParameterizedQuery();
// testColumnNames(); testColumnNames();
//
// testInsert(); testInsert();
// testUpdate(); testUpdate();
// testDelete(); testDelete();
// testMerge(); testMerge();
// testCreateTable(); testCreateTable();
// testNestedSQL(); testNestedSQL();
// testRecursiveTable(); testRecursiveTable();
// turn on special locking debug // turn on special locking debug
System.setProperty("h2.check2", "true"); System.setProperty("h2.check2", "true");
...@@ -620,6 +620,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -620,6 +620,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
PreparedStatement prep; PreparedStatement prep;
ResultSet rs; ResultSet rs;
for(int queryRunTries=1;queryRunTries<=maxRetries;queryRunTries++){ for(int queryRunTries=1;queryRunTries<=maxRetries;queryRunTries++){
System.out.println("Iteration #"+queryRunTries); System.out.println("Iteration #"+queryRunTries);
...@@ -662,6 +663,6 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -662,6 +663,6 @@ public class TestGeneralCommonTableQueries extends TestBase {
conn.close(); conn.close();
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
}
}
} }
...@@ -52,8 +52,8 @@ public class TestConnection extends TestBase { ...@@ -52,8 +52,8 @@ public class TestConnection extends TestBase {
} }
/** /**
* Test that no exception is thrown if the client info of a connection managed in a connection pool is reset * Test that no exception is thrown if the client info of a connection
* to its initial values. * managed in a connection pool is reset to its initial values.
* *
* This is needed when using h2 in websphere liberty. * This is needed when using h2 in websphere liberty.
*/ */
......
...@@ -1495,7 +1495,8 @@ public class TestMVTableEngine extends TestBase { ...@@ -1495,7 +1495,8 @@ public class TestMVTableEngine extends TestBase {
String dbName = getTestName() + ";MV_STORE=TRUE"; String dbName = getTestName() + ";MV_STORE=TRUE";
try (Connection conn = getConnection(dbName)) { try (Connection conn = getConnection(dbName)) {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR) AS SELECT x, x || space(1024) || x FROM system_range(1, 1000)"); stat.execute("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR) AS " +
"SELECT x, x || space(1024) || x FROM system_range(1, 1000)");
conn.setAutoCommit(false); conn.setAutoCommit(false);
PreparedStatement prep = conn.prepareStatement("DELETE FROM test WHERE id = ?"); PreparedStatement prep = conn.prepareStatement("DELETE FROM test WHERE id = ?");
long start = System.nanoTime(); long start = System.nanoTime();
......
...@@ -9,7 +9,6 @@ import java.io.IOException; ...@@ -9,7 +9,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
/** /**
...@@ -51,7 +50,8 @@ public class OutputCatcher extends Thread { ...@@ -51,7 +50,8 @@ public class OutputCatcher extends Thread {
@Override @Override
public void run() { public void run() {
StringBuilder buff = new StringBuilder(); final StringBuilder buff = new StringBuilder();
try {
while (true) { while (true) {
try { try {
int x = in.read(); int x = in.read();
...@@ -75,5 +75,14 @@ public class OutputCatcher extends Thread { ...@@ -75,5 +75,14 @@ public class OutputCatcher extends Thread {
} }
} }
IOUtils.closeSilently(in); IOUtils.closeSilently(in);
} finally {
// just in case something goes wrong, make sure we store any partial output we got
if (buff.length() > 0) {
synchronized (list) {
list.add(buff.toString());
list.notifyAll();
}
}
}
} }
} }
...@@ -9,7 +9,6 @@ import java.sql.PreparedStatement; ...@@ -9,7 +9,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.test.utils.SelfDestructor; import org.h2.test.utils.SelfDestructor;
/** /**
...@@ -38,6 +37,7 @@ public class TestHaltApp extends TestHalt { ...@@ -38,6 +37,7 @@ public class TestHaltApp extends TestHalt {
} }
} }
@Override
protected void execute(Statement stat, String sql) throws SQLException { protected void execute(Statement stat, String sql) throws SQLException {
traceOperation("execute: " + sql); traceOperation("execute: " + sql);
super.execute(stat, sql); super.execute(stat, sql);
......
...@@ -42,7 +42,7 @@ public class TestKillRestart extends TestBase { ...@@ -42,7 +42,7 @@ public class TestKillRestart extends TestBase {
int len = getSize(2, 15); int len = getSize(2, 15);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Process p = Runtime.getRuntime().exec(procDef); Process p = new ProcessBuilder().redirectErrorStream(true).command(procDef).start();
InputStream in = p.getInputStream(); InputStream in = p.getInputStream();
OutputCatcher catcher = new OutputCatcher(in); OutputCatcher catcher = new OutputCatcher(in);
catcher.start(); catcher.start();
......
...@@ -106,7 +106,8 @@ public class TestFileLockProcess extends TestBase { ...@@ -106,7 +106,8 @@ public class TestFileLockProcess extends TestBase {
} }
proc.waitFor(); proc.waitFor();
// The travis build somehow generates messages like this from javac. No idea where it is coming from. // The travis build somehow generates messages like this from javac.
// No idea where it is coming from.
String processOutput = buff.toString(); String processOutput = buff.toString();
processOutput = processOutput.replaceAll("Picked up _JAVA_OPTIONS: -Xmx2048m -Xms512m", "").trim(); processOutput = processOutput.replaceAll("Picked up _JAVA_OPTIONS: -Xmx2048m -Xms512m", "").trim();
......
...@@ -158,7 +158,9 @@ public class TestNetUtils extends TestBase { ...@@ -158,7 +158,9 @@ public class TestNetUtils extends TestBase {
*/ */
void closeSilently(Socket socket) { void closeSilently(Socket socket) {
try { try {
if (socket != null) {
socket.close(); socket.close();
}
} catch (Exception e) { } catch (Exception e) {
// ignore // ignore
} }
......
...@@ -368,7 +368,8 @@ public class TestPgServer extends TestBase { ...@@ -368,7 +368,8 @@ public class TestPgServer extends TestBase {
return; return;
} }
// Sometimes the previous pg server has not finished shutting and we get "port in use", so sleep for a bit. // Sometimes the previous pg server has not finished shutting and we get
// "port in use", so sleep for a bit.
Thread.sleep(100); Thread.sleep(100);
Server server = Server.createPgServer( Server server = Server.createPgServer(
......
...@@ -45,6 +45,7 @@ public class TestColumnNamer extends TestBase { ...@@ -45,6 +45,7 @@ public class TestColumnNamer extends TestBase {
new TestColumnNamer().test(); new TestColumnNamer().test();
} }
@Override
public void test() { public void test() {
ColumnNamer columnNamer = new ColumnNamer(null); ColumnNamer columnNamer = new ColumnNamer(null);
columnNamer.getConfiguration().configure("MAX_IDENTIFIER_LENGTH = 30"); columnNamer.getConfiguration().configure("MAX_IDENTIFIER_LENGTH = 30");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论