提交 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()));
......
...@@ -329,9 +329,10 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -329,9 +329,10 @@ public class AlterTableAddConstraint extends SchemaCommand {
} }
return null; return null;
} }
// 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()) {
...@@ -350,9 +351,9 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -350,9 +351,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
for (IndexColumn c : cols) { for (IndexColumn c : cols) {
colsSet.add(c.column); colsSet.add(c.column);
} }
return colsSet.equals(indexColsSet); return colsSet.equals(indexColsSet);
} }
private static boolean canUseIndex(Index existingIndex, Table table, private static boolean canUseIndex(Index existingIndex, Table table,
IndexColumn[] cols, boolean moreColumnsOk) { IndexColumn[] cols, boolean moreColumnsOk) {
......
...@@ -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,11 +303,9 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -306,11 +303,9 @@ 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);
}
} }
} }
......
...@@ -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,33 +98,19 @@ public class CreateView extends SchemaCommand { ...@@ -99,33 +98,19 @@ public class CreateView extends SchemaCommand {
} }
querySQL = select.getPlanSQL(); querySQL = select.getPlanSQL();
} }
// The view creates a Prepared command object, which belongs to a Column[] columnTemplates = null;
// session, so we pass the system session (not the current session) down. if (columnNames != null) {
// Why is the SYS session used here ? I think it might cause a problem... columnTemplates = new Column[columnNames.length];
Session sysSession = db.getSystemSession(); for (int i = 0; i < columnNames.length; ++i) {
synchronized (sysSession) { columnTemplates[i] = new Column(columnNames[i], Value.UNKNOWN);
try {
Column[] columnTemplates = null;
if (columnNames != null) {
columnTemplates = new Column[columnNames.length];
for (int i = 0; i < columnNames.length; ++i) {
columnTemplates[i] = new Column(columnNames[i], Value.UNKNOWN);
}
}
if (view == null) {
Schema schema = session.getDatabase().getSchema(
session.getCurrentSchemaName());
sysSession.setCurrentSchema(schema);
view = new TableView(getSchema(), id, viewName, querySQL, null,
columnTemplates, sysSession, false, false);
} else {
view.replace(querySQL, columnTemplates, sysSession, false, force, false);
view.setModified();
}
} finally {
sysSession.setCurrentSchema(db.getSchema(Constants.SCHEMA_MAIN));
} }
} }
if (view == null) {
view = new TableView(getSchema(), id, viewName, querySQL, null, columnTemplates, session, false, false);
} else {
view.replace(querySQL, columnTemplates, session, false, force, false);
view.setModified();
}
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);
......
...@@ -1739,11 +1739,12 @@ public class JdbcConnection extends TraceObject ...@@ -1739,11 +1739,12 @@ 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;
} }
if (isInternalProperty(name)) { if (isInternalProperty(name)) {
......
...@@ -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,18 +305,16 @@ public class Sequence extends SchemaObjectBase { ...@@ -306,18 +305,16 @@ 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 { writeWithMargin = true;
writeWithMargin = true; database.updateMeta(session, this);
database.updateMeta(session, this); } finally {
} finally { writeWithMargin = false;
writeWithMargin = false; }
} if (!metaWasLocked) {
if (!metaWasLocked) { database.unlockMeta(session);
database.unlockMeta(session);
}
} }
} }
......
...@@ -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,17 +136,12 @@ public class TableView extends Table { ...@@ -136,17 +136,12 @@ 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) {
...@@ -157,14 +152,14 @@ public class TableView extends Table { ...@@ -157,14 +152,14 @@ 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();
tables = New.arrayList(compiledQuery.getTables()); tables = New.arrayList(compiledQuery.getTables());
ArrayList<Expression> expressions = compiledQuery.getExpressions(); ArrayList<Expression> expressions = compiledQuery.getExpressions();
ArrayList<Column> list = New.arrayList(); ArrayList<Column> list = New.arrayList();
ColumnNamer columnNamer= new ColumnNamer(session); ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0, count = compiledQuery.getColumnCount(); i < count; i++) { for (int i = 0, count = compiledQuery.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i); Expression expr = expressions.get(i);
String name = null; String name = null;
...@@ -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;
......
...@@ -13,7 +13,7 @@ public class ColumnNamerConfiguration { ...@@ -13,7 +13,7 @@ public class ColumnNamerConfiguration {
private static final String MAX_IDENTIFIER_LENGTH = "MAX_IDENTIFIER_LENGTH = "; private static final String MAX_IDENTIFIER_LENGTH = "MAX_IDENTIFIER_LENGTH = ";
private static final String EMULATE_COMMAND = "EMULATE = "; private static final String EMULATE_COMMAND = "EMULATE = ";
private static final String GENERATE_UNIQUE_COLUMN_NAMES = "GENERATE_UNIQUE_COLUMN_NAMES = "; private static final String GENERATE_UNIQUE_COLUMN_NAMES = "GENERATE_UNIQUE_COLUMN_NAMES = ";
private int maxIdentiferLength; private int maxIdentiferLength;
private String regularExpressionMatchAllowed; private String regularExpressionMatchAllowed;
private String regularExpressionMatchDisallowed; private String regularExpressionMatchDisallowed;
...@@ -23,14 +23,15 @@ public class ColumnNamerConfiguration { ...@@ -23,14 +23,15 @@ 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;
this.regularExpressionMatchDisallowed = regularExpressionMatchDisallowed; this.regularExpressionMatchDisallowed = regularExpressionMatchDisallowed;
this.defaultColumnNamePattern = defaultColumnNamePattern; this.defaultColumnNamePattern = defaultColumnNamePattern;
this.generateUniqueColumnNames = generateUniqueColumnNames; this.generateUniqueColumnNames = generateUniqueColumnNames;
compiledRegularExpressionMatchAllowed = Pattern.compile(regularExpressionMatchAllowed); compiledRegularExpressionMatchAllowed = Pattern.compile(regularExpressionMatchAllowed);
compiledRegularExpressionMatchDisallowed = Pattern.compile(regularExpressionMatchDisallowed); compiledRegularExpressionMatchDisallowed = Pattern.compile(regularExpressionMatchDisallowed);
} }
...@@ -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);
} }
} }
...@@ -85,32 +87,35 @@ public class ColumnNamerConfiguration { ...@@ -85,32 +87,35 @@ public class ColumnNamerConfiguration {
public void setCompiledRegularExpressionMatchDisallowed(Pattern compiledRegularExpressionMatchDisallowed) { public void setCompiledRegularExpressionMatchDisallowed(Pattern compiledRegularExpressionMatchDisallowed) {
this.compiledRegularExpressionMatchDisallowed = compiledRegularExpressionMatchDisallowed; this.compiledRegularExpressionMatchDisallowed = compiledRegularExpressionMatchDisallowed;
} }
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);
} }
recompilePatterns(); recompilePatterns();
} }
//Including NumberFormatException|PatternSyntaxException //Including NumberFormatException|PatternSyntaxException
...@@ -118,7 +123,7 @@ public class ColumnNamerConfiguration { ...@@ -118,7 +123,7 @@ public class ColumnNamerConfiguration {
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES:"+e.getMessage(), throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES:"+e.getMessage(),
stringValue); stringValue);
} }
} }
private void recompilePatterns() { private void recompilePatterns() {
...@@ -131,12 +136,12 @@ public class ColumnNamerConfiguration { ...@@ -131,12 +136,12 @@ public class ColumnNamerConfiguration {
configure(REGULAR); configure(REGULAR);
throw e; throw e;
} }
} }
public static ColumnNamerConfiguration getDefault(){ public static ColumnNamerConfiguration getDefault(){
return new ColumnNamerConfiguration(Integer.MAX_VALUE, "(?m)(?s).+", "(?m)(?s)[\\x00]", "_UNNAMED_$$",false); return new ColumnNamerConfiguration(Integer.MAX_VALUE, "(?m)(?s).+", "(?m)(?s)[\\x00]", "_UNNAMED_$$",false);
} }
private static String unquoteString(String s){ private static String unquoteString(String s){
if(s.startsWith("'") && s.endsWith("'")){ if(s.startsWith("'") && s.endsWith("'")){
s = s.substring(1, s.length()-1); s = s.substring(1, s.length()-1);
...@@ -156,30 +161,31 @@ public class ColumnNamerConfiguration { ...@@ -156,30 +161,31 @@ public class ColumnNamerConfiguration {
public void configure(ModeEnum modeEnum) { public void configure(ModeEnum modeEnum) {
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_\"\\$#]");
setDefaultColumnNamePattern("_UNNAMED_$$"); setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false); setGenerateUniqueColumnNames(false);
break; break;
case MSSQLServer: case MSSQLServer:
// https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server // https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server
setMaxIdentiferLength(128); setMaxIdentiferLength(128);
setRegularExpressionMatchAllowed("(?m)(?s)[A-Za-z0-9_\\[\\]]+");// allows [] around names setRegularExpressionMatchAllowed("(?m)(?s)[A-Za-z0-9_\\[\\]]+");// allows [] around names
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\\[\\]]"); setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\\[\\]]");
setDefaultColumnNamePattern("_UNNAMED_$$"); setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false); setGenerateUniqueColumnNames(false);
break; break;
case PostgreSQL: case PostgreSQL:
setMaxIdentiferLength(63);// this default can be changed to 128 by postgres config setMaxIdentiferLength(63);// this default can be changed to 128 by postgres config
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_\\$]");
setDefaultColumnNamePattern("_UNNAMED_$$"); setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false); setGenerateUniqueColumnNames(false);
break; break;
case MySQL: case MySQL:
...@@ -190,7 +196,7 @@ public class ColumnNamerConfiguration { ...@@ -190,7 +196,7 @@ public class ColumnNamerConfiguration {
setDefaultColumnNamePattern("_UNNAMED_$$"); setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false); setGenerateUniqueColumnNames(false);
break; break;
default: default:
case REGULAR: case REGULAR:
case DB2: case DB2:
...@@ -204,7 +210,7 @@ public class ColumnNamerConfiguration { ...@@ -204,7 +210,7 @@ public class ColumnNamerConfiguration {
setGenerateUniqueColumnNames(false); setGenerateUniqueColumnNames(false);
break; break;
} }
recompilePatterns(); recompilePatterns();
} }
} }
\ No newline at end of file
...@@ -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,17 +55,19 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -55,17 +55,19 @@ 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");
// Some other variation with oracle syntax // Some other variation with oracle syntax
stat.execute("create table T (C int not null)"); stat.execute("create table T (C int not null)");
stat.execute("insert into T values(1)"); stat.execute("insert into T values(1)");
stat.execute("alter table T modify C not null"); stat.execute("alter table T modify C not null");
stat.execute("insert into T values(1)"); stat.execute("insert into T values(1)");
stat.execute("alter table T modify C not null enable"); stat.execute("alter table T modify C not null enable");
stat.execute("insert into T values(1)"); stat.execute("insert into T values(1)");
...@@ -78,17 +80,19 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -78,17 +80,19 @@ 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");
conn.close(); conn.close();
} }
private void testSpecialTypes() throws SQLException { private void testSpecialTypes() throws SQLException {
// Test VARCHAR, VARCHAR2 with CHAR and BYTE // Test VARCHAR, VARCHAR2 with CHAR and BYTE
deleteDb("oracle"); deleteDb("oracle");
Connection conn = getConnection("oracle;MODE=Oracle"); Connection conn = getConnection("oracle;MODE=Oracle");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
...@@ -96,7 +100,7 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -96,7 +100,7 @@ public class TestCompatibilityOracle extends TestBase {
stat.execute("alter table T add A_1 VARCHAR(1)"); stat.execute("alter table T add A_1 VARCHAR(1)");
stat.execute("alter table T add A_2 VARCHAR2(1)"); stat.execute("alter table T add A_2 VARCHAR2(1)");
stat.execute("alter table T add B_1 VARCHAR(1 byte)"); // with BYTE stat.execute("alter table T add B_1 VARCHAR(1 byte)"); // with BYTE
stat.execute("alter table T add B_2 VARCHAR2(1 byte)"); stat.execute("alter table T add B_2 VARCHAR2(1 byte)");
stat.execute("alter table T add C_1 VARCHAR(1 char)"); // with CHAR stat.execute("alter table T add C_1 VARCHAR(1 char)"); // with CHAR
stat.execute("alter table T add C_2 VARCHAR2(1 char)"); stat.execute("alter table T add C_2 VARCHAR2(1 char)");
stat.execute("alter table T add B_255 VARCHAR(255 byte)"); stat.execute("alter table T add B_255 VARCHAR(255 byte)");
...@@ -104,7 +108,7 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -104,7 +108,7 @@ public class TestCompatibilityOracle extends TestBase {
stat.execute("drop table T"); stat.execute("drop table T");
conn.close(); conn.close();
} }
private void testTreatEmptyStringsAsNull() throws SQLException { private void testTreatEmptyStringsAsNull() throws SQLException {
deleteDb("oracle"); deleteDb("oracle");
Connection conn = getConnection("oracle;MODE=Oracle"); Connection conn = getConnection("oracle;MODE=Oracle");
......
...@@ -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");
...@@ -398,7 +398,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -398,7 +398,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
conn.close(); conn.close();
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
} }
private void testNestedSQL() throws Exception { private void testNestedSQL() throws Exception {
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries"); Connection conn = getConnection("commonTableExpressionQueries");
...@@ -446,7 +446,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -446,7 +446,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
} }
conn.close(); conn.close();
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
} }
private void testColumnNames() throws Exception { private void testColumnNames() throws Exception {
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
...@@ -477,7 +477,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -477,7 +477,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
conn.close(); conn.close();
deleteDb("commonTableExpressionQueries"); deleteDb("commonTableExpressionQueries");
} }
private void testRecursiveTable() throws Exception { private void testRecursiveTable() throws Exception {
int maxRetries = 4; int maxRetries = 4;
...@@ -619,6 +619,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -619,6 +619,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
Connection conn = getConnection("commonTableExpressionQueries"); Connection conn = getConnection("commonTableExpressionQueries");
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);
...@@ -643,7 +644,7 @@ public class TestGeneralCommonTableQueries extends TestBase { ...@@ -643,7 +644,7 @@ public class TestGeneralCommonTableQueries extends TestBase {
assertTrue(rs.getMetaData().getColumnLabel(columnIndex)!=null); assertTrue(rs.getMetaData().getColumnLabel(columnIndex)!=null);
assertEquals(expectedColumnNames[columnIndex-1],rs.getMetaData().getColumnLabel(columnIndex)); assertEquals(expectedColumnNames[columnIndex-1],rs.getMetaData().getColumnLabel(columnIndex));
} }
int rowNdx=0; int rowNdx=0;
while (rs.next()) { while (rs.next()) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
...@@ -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");
}
}
} }
...@@ -50,24 +50,24 @@ public class TestConnection extends TestBase { ...@@ -50,24 +50,24 @@ public class TestConnection extends TestBase {
assertThrows(SQLClientInfoException.class, conn).setClientInfo("server23", "SomeValue"); assertThrows(SQLClientInfoException.class, conn).setClientInfo("server23", "SomeValue");
conn.close(); conn.close();
} }
/** /**
* 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.
*/ */
private void testSetInternalPropertyToInitialValue() throws SQLException { private void testSetInternalPropertyToInitialValue() throws SQLException {
// Use MySQL-mode since this allows all property names // Use MySQL-mode since this allows all property names
// (apart from h2 internal names). // (apart from h2 internal names).
Connection conn = getConnection("clientInfoMySQL;MODE=MySQL"); Connection conn = getConnection("clientInfoMySQL;MODE=MySQL");
String numServersPropertyName = "numServers"; String numServersPropertyName = "numServers";
String numServers = conn.getClientInfo(numServersPropertyName); String numServers = conn.getClientInfo(numServersPropertyName);
conn.setClientInfo(numServersPropertyName, numServers); conn.setClientInfo(numServersPropertyName, numServers);
assertEquals(conn.getClientInfo(numServersPropertyName), numServers); assertEquals(conn.getClientInfo(numServersPropertyName), numServers);
conn.close(); conn.close();
......
...@@ -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,29 +50,39 @@ public class OutputCatcher extends Thread { ...@@ -51,29 +50,39 @@ public class OutputCatcher extends Thread {
@Override @Override
public void run() { public void run() {
StringBuilder buff = new StringBuilder(); final StringBuilder buff = new StringBuilder();
while (true) { try {
try { while (true) {
int x = in.read(); try {
if (x < 0) { int x = in.read();
break; if (x < 0) {
} break;
if (x < ' ') { }
if (buff.length() > 0) { if (x < ' ') {
String s = buff.toString(); if (buff.length() > 0) {
buff.setLength(0); String s = buff.toString();
synchronized (list) { buff.setLength(0);
list.add(s); synchronized (list) {
list.notifyAll(); list.add(s);
list.notifyAll();
}
} }
} else {
buff.append((char) x);
} }
} else { } catch (IOException e) {
buff.append((char) x); break;
}
}
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();
} }
} catch (IOException e) {
break;
} }
} }
IOUtils.closeSilently(in);
} }
} }
...@@ -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 {
socket.close(); if (socket != null) {
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(
......
...@@ -6,7 +6,7 @@ import org.h2.expression.ValueExpression; ...@@ -6,7 +6,7 @@ import org.h2.expression.ValueExpression;
import org.h2.test.TestBase; import org.h2.test.TestBase;
public class TestColumnNamer extends TestBase { public class TestColumnNamer extends TestBase {
private String[] ids = new String[]{ private String[] ids = new String[]{
"ABC" "ABC"
,"123" ,"123"
...@@ -24,7 +24,7 @@ public class TestColumnNamer extends TestBase { ...@@ -24,7 +24,7 @@ public class TestColumnNamer extends TestBase {
,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2" ,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2"
,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2" ,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2"
}; };
private String[] expectedColumnName= {"ABC" private String[] expectedColumnName= {"ABC"
,"123" ,"123"
,"a2" ,"a2"
...@@ -39,12 +39,13 @@ public class TestColumnNamer extends TestBase { ...@@ -39,12 +39,13 @@ public class TestColumnNamer extends TestBase {
,"col1_2" ,"col1_2"
,"col1_3" ,"col1_3"
,"col2col2col2col2col2col2col2co" ,"col2col2col2col2col2col2col2co"
,"col2col2col2col2col2col2col2_2"}; ,"col2col2col2col2col2col2col2_2"};
public static void main(String[] args){ public static void main(String[] args){
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");
...@@ -52,7 +53,7 @@ public class TestColumnNamer extends TestBase { ...@@ -52,7 +53,7 @@ public class TestColumnNamer extends TestBase {
columnNamer.getConfiguration().configure("REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+'"); columnNamer.getConfiguration().configure("REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+'");
columnNamer.getConfiguration().configure("DEFAULT_COLUMN_NAME_PATTERN = 'colName$$'"); columnNamer.getConfiguration().configure("DEFAULT_COLUMN_NAME_PATTERN = 'colName$$'");
columnNamer.getConfiguration().configure("GENERATE_UNIQUE_COLUMN_NAMES = 1"); columnNamer.getConfiguration().configure("GENERATE_UNIQUE_COLUMN_NAMES = 1");
int index =0; int index =0;
for(String id : ids){ for(String id : ids){
Expression columnExp = ValueExpression.getDefault(); Expression columnExp = ValueExpression.getDefault();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论