提交 b5588073 authored 作者: andrei's avatar andrei

Merge remote-tracking branch 'h2database/master' into issue#499.2

...@@ -11,5 +11,9 @@ ...@@ -11,5 +11,9 @@
/test.out.txt /test.out.txt
.DS_Store .DS_Store
/.idea/ /.idea/
*.iml
*.ipr
*.iws
.checkstyle .checkstyle
/temp/ /temp/
/h2web/
\ No newline at end of file
sudo: false
language: java language: java
jdk:
- openjdk7
- oraclejdk8
before_script: cd h2
script: ./build.sh jar testFast script: ./build.sh jar testFast
cache: cache:
directories: directories:
- $HOME/.m2/repository - $HOME/.m2/repository
matrix:
include:
- jdk: oraclejdk8
dist: trusty
group: edge
sudo: required
addons:
apt:
packages:
- oracle-java8-installer
before_script:
- "cd h2"
- "echo $JAVA_OPTS"
- "export JAVA_OPTS=-Xmx512m"
- jdk: openjdk7
dist: trusty
group: edge
sudo: required
addons:
apt:
packages:
- openjdk-7-jdk
before_script:
- "cd h2"
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<version>1.4.194-SNAPSHOT</version> <version>1.4.196-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>H2 Database Engine</name> <name>H2 Database Engine</name>
<url>http://www.h2database.com</url> <url>http://www.h2database.com</url>
......
...@@ -193,12 +193,14 @@ SHOW TABLES ...@@ -193,12 +193,14 @@ SHOW TABLES
" "
"Commands (DML)","WITH"," "Commands (DML)","WITH","
WITH [ RECURSIVE ] name ( columnName [,...] ) WITH [ RECURSIVE ] { name [( columnName [,...] )]
AS ( select ) AS ( select ) [,...] }
select select
"," ","
Can be used to create a recursive query. The first select has to be a UNION. Can be used to create a recursive or non-recursive query (common table expression).
Currently only one result set can be referred to by name. For recursive queries the first select has to be a UNION.
One or more common table entries can be referred to by name.
Column name declarations are now optional - the column names will be inferred from the named select queries.
"," ","
WITH RECURSIVE t(n) AS ( WITH RECURSIVE t(n) AS (
SELECT 1 SELECT 1
...@@ -208,6 +210,13 @@ WITH RECURSIVE t(n) AS ( ...@@ -208,6 +210,13 @@ WITH RECURSIVE t(n) AS (
WHERE n < 100 WHERE n < 100
) )
SELECT sum(n) FROM t; SELECT sum(n) FROM t;
","
WITH t1 AS (
SELECT 1 AS FIRST_COLUMN
), t2 AS (
SELECT FIRST_COLUMN+1 AS FIRST_COLUMN FROM t1
)
SELECT sum(FIRST_COLUMN) FROM t2;
" "
"Commands (DDL)","ALTER INDEX RENAME"," "Commands (DDL)","ALTER INDEX RENAME","
......
...@@ -21,6 +21,14 @@ Change Log ...@@ -21,6 +21,14 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>-
</li>
</ul>
<h2>Version 1.4.196 (2017-06-10)</h2>
<ul>
<li>Issue#479 Allow non-recursive CTEs (WITH statements), patch from stumc
</li>
<li>Fix startup issue when using "CHECK" as a column name. <li>Fix startup issue when using "CHECK" as a column name.
</li> </li>
<li>Issue #423: ANALYZE performed multiple times on one table during execution of the same statement. <li>Issue #423: ANALYZE performed multiple times on one table during execution of the same statement.
...@@ -31,6 +39,10 @@ Change Log ...@@ -31,6 +39,10 @@ Change Log
</li> </li>
<li>Issue #472: Support CREATE SEQUENCE ... ORDER as a NOOP for Oracle compatibility <li>Issue #472: Support CREATE SEQUENCE ... ORDER as a NOOP for Oracle compatibility
</li> </li>
<li>Issue #479: Allow non-recursive Common Table Expressions (CTE)
</li>
<li>On Mac OS X, with IPv6 and no network connection, the Console tool was not working as expected.
</li>
</ul> </ul>
<h2>Version 1.4.195 (2017-04-23)</h2> <h2>Version 1.4.195 (2017-04-23)</h2>
...@@ -201,6 +213,8 @@ changed from Types.OTHER (1111) to Types.TIMESTAMP_WITH_TIMEZONE (2014) ...@@ -201,6 +213,8 @@ changed from Types.OTHER (1111) to Types.TIMESTAMP_WITH_TIMEZONE (2014)
<h2>Version 1.4.192 Beta (2016-05-26)</h2> <h2>Version 1.4.192 Beta (2016-05-26)</h2>
<ul> <ul>
<li>Java 6 is no longer supported (the jar files are compiled for Java 7).
</li>
<li>Garbage collection of unused chunks should now be faster. <li>Garbage collection of unused chunks should now be faster.
</li> </li>
<li>Prevent people using unsupported combination of auto-increment columns and clustering mode. <li>Prevent people using unsupported combination of auto-increment columns and clustering mode.
......
...@@ -28,7 +28,7 @@ Add to http://twitter.com ...@@ -28,7 +28,7 @@ Add to http://twitter.com
Sign files and publish files on Maven Central Sign files and publish files on Maven Central
(check java version is 1.7) (check java version is 1.7)
./build.sh compile jar mavenDeployCentral ./build.sh clean compile jar mavenDeployCentral
cd /data/h2database/m2-repo/com/h2database cd /data/h2database/m2-repo/com/h2database
# remove sha and md5 files: # remove sha and md5 files:
find . -name "*.sha1" -delete find . -name "*.sha1" -delete
......
...@@ -112,7 +112,7 @@ public abstract class Command implements CommandInterface { ...@@ -112,7 +112,7 @@ public abstract class Command implements CommandInterface {
* @return the local result set * @return the local result set
* @throws DbException if the command is not a query * @throws DbException if the command is not a query
*/ */
public ResultInterface query(int maxrows) { public ResultInterface query(@SuppressWarnings("unused") int maxrows) {
throw DbException.get(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY); throw DbException.get(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
} }
......
...@@ -17,6 +17,7 @@ import java.util.Collections; ...@@ -17,6 +17,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.Trigger; import org.h2.api.Trigger;
import org.h2.command.ddl.AlterIndexRename; import org.h2.command.ddl.AlterIndexRename;
...@@ -4855,16 +4856,34 @@ public class Parser { ...@@ -4855,16 +4856,34 @@ public class Parser {
} }
private Query parseWith() { private Query parseWith() {
List<TableView> viewsCreated = new ArrayList<TableView>();
readIf("RECURSIVE"); readIf("RECURSIVE");
do {
viewsCreated.add(parseSingleCommonTableExpression());
} while (readIf(","));
Query q = parseSelectUnion();
q.setPrepareAlways(true);
return q;
}
private TableView parseSingleCommonTableExpression() {
String tempViewName = readIdentifierWithSchema(); String tempViewName = readIdentifierWithSchema();
Schema schema = getSchema(); Schema schema = getSchema();
Table recursiveTable; Table recursiveTable;
read("(");
ArrayList<Column> columns = New.arrayList(); ArrayList<Column> columns = New.arrayList();
String[] cols = parseColumnList(); String[] cols = null;
// column names are now optional - they can be inferred from the named
// query if not supplied
if (readIf("(")) {
cols = parseColumnList();
for (String c : cols) { for (String c : cols) {
// we dont really know the type of the column, so string will
// have to do
columns.add(new Column(c, Value.STRING)); columns.add(new Column(c, Value.STRING));
} }
}
Table old = session.findLocalTempTable(tempViewName); Table old = session.findLocalTempTable(tempViewName);
if (old != null) { if (old != null) {
if (!(old instanceof TableView)) { if (!(old instanceof TableView)) {
...@@ -4878,6 +4897,10 @@ public class Parser { ...@@ -4878,6 +4897,10 @@ public class Parser {
} }
session.removeLocalTempTable(old); session.removeLocalTempTable(old);
} }
// this table is created as a work around because recursive
// table expressions need to reference something that look like
// themselves
// to work (its removed after creation in this method)
CreateTableData data = new CreateTableData(); CreateTableData data = new CreateTableData();
data.id = database.allocateObjectId(); data.id = database.allocateObjectId();
data.columns = columns; data.columns = columns;
...@@ -4890,7 +4913,7 @@ public class Parser { ...@@ -4890,7 +4913,7 @@ public class Parser {
recursiveTable = schema.createTable(data); recursiveTable = schema.createTable(data);
session.addLocalTempTable(recursiveTable); session.addLocalTempTable(recursiveTable);
String querySQL; String querySQL;
Column[] columnTemplates = new Column[cols.length]; List<Column> columnTemplateList = new ArrayList<Column>();
try { try {
read("AS"); read("AS");
read("("); read("(");
...@@ -4899,22 +4922,32 @@ public class Parser { ...@@ -4899,22 +4922,32 @@ public class Parser {
withQuery.prepare(); withQuery.prepare();
querySQL = StringUtils.cache(withQuery.getPlanSQL()); querySQL = StringUtils.cache(withQuery.getPlanSQL());
ArrayList<Expression> withExpressions = withQuery.getExpressions(); ArrayList<Expression> withExpressions = withQuery.getExpressions();
for (int i = 0; i < cols.length; ++i) { for (int i = 0; i < withExpressions.size(); ++i) {
columnTemplates[i] = new Column(cols[i], withExpressions.get(i).getType()); String columnName = cols != null ? cols[i]
: withExpressions.get(i).getColumnName();
columnTemplateList.add(new Column(columnName,
withExpressions.get(i).getType()));
} }
} finally { } finally {
session.removeLocalTempTable(recursiveTable); session.removeLocalTempTable(recursiveTable);
} }
int id = database.allocateObjectId(); int id = database.allocateObjectId();
// No easy way to determine if this is a recursive query up front, so we just compile
// it twice - once without the flag set, and if we didn't see a recursive term,
// then we just compile it again.
TableView view = new TableView(schema, id, tempViewName, querySQL, TableView view = new TableView(schema, id, tempViewName, querySQL,
parameters, columnTemplates, session, true); parameters, columnTemplateList.toArray(new Column[0]), session,
true/* recursive */);
if (!view.isRecursiveQueryDetected()) {
view = new TableView(schema, id, tempViewName, querySQL, parameters,
columnTemplateList.toArray(new Column[0]), session,
false/* recursive */);
}
view.setTableExpression(true); view.setTableExpression(true);
view.setTemporary(true); view.setTemporary(true);
session.addLocalTempTable(view); session.addLocalTempTable(view);
view.setOnCommitDrop(true); view.setOnCommitDrop(true);
Query q = parseSelectUnion(); return view;
q.setPrepareAlways(true);
return q;
} }
private CreateView parseCreateView(boolean force, boolean orReplace) { private CreateView parseCreateView(boolean force, boolean orReplace) {
......
...@@ -208,6 +208,7 @@ public abstract class Prepared { ...@@ -208,6 +208,7 @@ public abstract class Prepared {
* @return the result set * @return the result set
* @throws DbException if it is not a query * @throws DbException if it is not a query
*/ */
@SuppressWarnings("unused")
public ResultInterface query(int maxrows) { public ResultInterface query(int maxrows) {
throw DbException.get(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY); throw DbException.get(ErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY);
} }
......
...@@ -118,7 +118,7 @@ public class CreateView extends SchemaCommand { ...@@ -118,7 +118,7 @@ public class CreateView extends SchemaCommand {
view = new TableView(getSchema(), id, viewName, querySQL, null, view = new TableView(getSchema(), id, viewName, querySQL, null,
columnTemplates, sysSession, false); columnTemplates, sysSession, false);
} else { } else {
view.replace(querySQL, columnNames, sysSession, false, force); view.replace(querySQL, sysSession, false, force);
view.setModified(); view.setModified();
} }
} finally { } finally {
......
...@@ -192,7 +192,7 @@ public abstract class Constraint extends SchemaObjectBase implements ...@@ -192,7 +192,7 @@ public abstract class Constraint extends SchemaObjectBase implements
* @return true if every visited expression returned true, or if there are * @return true if every visited expression returned true, or if there are
* no expressions * no expressions
*/ */
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(@SuppressWarnings("unused") ExpressionVisitor visitor) {
return true; return true;
} }
......
...@@ -16,22 +16,22 @@ public class Constants { ...@@ -16,22 +16,22 @@ public class Constants {
/** /**
* The build date is updated for each public release. * The build date is updated for each public release.
*/ */
public static final String BUILD_DATE = "2017-04-23"; public static final String BUILD_DATE = "2017-06-10";
/** /**
* The build date of the last stable release. * The build date of the last stable release.
*/ */
public static final String BUILD_DATE_STABLE = "2017-03-10"; public static final String BUILD_DATE_STABLE = "2017-04-23";
/** /**
* The build id is incremented for each public release. * The build id is incremented for each public release.
*/ */
public static final int BUILD_ID = 195; public static final int BUILD_ID = 196;
/** /**
* The build id of the last stable release. * The build id of the last stable release.
*/ */
public static final int BUILD_ID_STABLE = 194; public static final int BUILD_ID_STABLE = 195;
/** /**
* Whether this is a snapshot version. * Whether this is a snapshot version.
......
...@@ -1695,6 +1695,11 @@ public class Session extends SessionWithState { ...@@ -1695,6 +1695,11 @@ public class Session extends SessionWithState {
return false; return false;
} }
/**
* Mark that the given table needs to be analyzed on commit.
*
* @param table the table
*/
public void markTableForAnalyze(Table table) { public void markTableForAnalyze(Table table) {
if (tablesToAnalyze == null) { if (tablesToAnalyze == null) {
tablesToAnalyze = New.hashSet(); tablesToAnalyze = New.hashSet();
......
...@@ -134,7 +134,7 @@ public abstract class Expression { ...@@ -134,7 +134,7 @@ public abstract class Expression {
* @param session the session * @param session the session
* @return the negated expression, or null * @return the negated expression, or null
*/ */
public Expression getNotIfPossible(Session session) { public Expression getNotIfPossible(@SuppressWarnings("unused") Session session) {
// by default it is not possible // by default it is not possible
return null; return null;
} }
...@@ -184,6 +184,7 @@ public abstract class Expression { ...@@ -184,6 +184,7 @@ public abstract class Expression {
* @param session the session * @param session the session
* @param filter the table filter * @param filter the table filter
*/ */
@SuppressWarnings("unused")
public void createIndexConditions(Session session, TableFilter filter) { public void createIndexConditions(Session session, TableFilter filter) {
// default is do nothing // default is do nothing
} }
...@@ -292,6 +293,7 @@ public abstract class Expression { ...@@ -292,6 +293,7 @@ public abstract class Expression {
* @param session the session * @param session the session
* @return array of expression columns if applicable, null otherwise * @return array of expression columns if applicable, null otherwise
*/ */
@SuppressWarnings("unused")
public Expression[] getExpressionColumns(Session session) { public Expression[] getExpressionColumns(Session session) {
return null; return null;
} }
......
...@@ -74,6 +74,7 @@ public class IndexType { ...@@ -74,6 +74,7 @@ public class IndexType {
/** /**
* Create an affinity index. * Create an affinity index.
* *
* @return the index type
*/ */
public static IndexType createAffinity() { public static IndexType createAffinity() {
IndexType type = new IndexType(); IndexType type = new IndexType();
......
...@@ -180,11 +180,10 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex { ...@@ -180,11 +180,10 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
/** /**
* Compute spatial index cost * Compute spatial index cost
* @param masks Search mask * @param masks Search mask
* @param rowCount Table row count
* @param columns Table columns * @param columns Table columns
* @return Index cost hint * @return Index cost hint
*/ */
public static long getCostRangeIndex(int[] masks, long rowCount, Column[] columns) { public static long getCostRangeIndex(int[] masks, Column[] columns) {
// Never use spatial tree index without spatial filter // Never use spatial tree index without spatial filter
if (columns.length == 0) { if (columns.length == 0) {
return Long.MAX_VALUE; return Long.MAX_VALUE;
...@@ -203,7 +202,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex { ...@@ -203,7 +202,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
public double getCost(Session session, int[] masks, public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder, TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) { HashSet<Column> allColumnsSet) {
return getCostRangeIndex(masks, table.getRowCountApproximation(), columns); return getCostRangeIndex(masks, columns);
} }
......
...@@ -12,7 +12,6 @@ import java.sql.SQLWarning; ...@@ -12,7 +12,6 @@ import java.sql.SQLWarning;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Command;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.engine.SessionInterface; import org.h2.engine.SessionInterface;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
......
...@@ -206,6 +206,7 @@ public class StreamStore { ...@@ -206,6 +206,7 @@ public class StreamStore {
* *
* @param len the length of the stored block. * @param len the length of the stored block.
*/ */
@SuppressWarnings("unused")
protected void onStore(int len) { protected void onStore(int len) {
// do nothing by default // do nothing by default
} }
......
...@@ -174,6 +174,7 @@ public class CacheLongKeyLIRS<V> { ...@@ -174,6 +174,7 @@ public class CacheLongKeyLIRS<V> {
* @param value the value * @param value the value
* @return the size * @return the size
*/ */
@SuppressWarnings("unused")
protected int sizeOf(V value) { protected int sizeOf(V value) {
return 1; return 1;
} }
......
...@@ -253,8 +253,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -253,8 +253,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
public double getCost(Session session, int[] masks, TableFilter[] filters, public double getCost(Session session, int[] masks, TableFilter[] filters,
int filter, SortOrder sortOrder, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) { HashSet<Column> allColumnsSet) {
return SpatialTreeIndex.getCostRangeIndex(masks, return SpatialTreeIndex.getCostRangeIndex(masks, columns);
table.getRowCountApproximation(), columns);
} }
@Override @Override
......
...@@ -735,7 +735,6 @@ public class MVTable extends TableBase { ...@@ -735,7 +735,6 @@ public class MVTable extends TableBase {
if (n > 0) { if (n > 0) {
nextAnalyze = n; nextAnalyze = n;
} }
int rows = session.getDatabase().getSettings().analyzeSample / 10;
session.markTableForAnalyze(this); session.markTableForAnalyze(this);
} }
......
...@@ -7,7 +7,6 @@ package org.h2.mvstore.rtree; ...@@ -7,7 +7,6 @@ package org.h2.mvstore.rtree;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import org.h2.mvstore.CursorPos; import org.h2.mvstore.CursorPos;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap; import org.h2.mvstore.MVMap;
...@@ -556,6 +555,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -556,6 +555,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
* @param test the user-supplied test key * @param test the user-supplied test key
* @return true if there is a match * @return true if there is a match
*/ */
@SuppressWarnings("unused")
protected boolean check(boolean leaf, SpatialKey key, SpatialKey test) { protected boolean check(boolean leaf, SpatialKey key, SpatialKey test) {
return true; return true;
} }
......
...@@ -67,11 +67,11 @@ SHOW { SCHEMAS | TABLES [ FROM schemaName ] | ...@@ -67,11 +67,11 @@ SHOW { SCHEMAS | TABLES [ FROM schemaName ] |
"," ","
Lists the schemas, tables, or the columns of a table." Lists the schemas, tables, or the columns of a table."
"Commands (DML)","WITH"," "Commands (DML)","WITH","
WITH [ RECURSIVE ] name ( columnName [,...] ) WITH [ RECURSIVE ] { name [( columnName [,...] )]
AS ( select ) AS ( select ) [,...] }
select select
"," ","
Can be used to create a recursive query." Can be used to create a recursive or non-recursive query (common table expression)."
"Commands (DDL)","ALTER INDEX RENAME"," "Commands (DDL)","ALTER INDEX RENAME","
ALTER INDEX [ IF EXISTS ] indexName RENAME TO newIndexName ALTER INDEX [ IF EXISTS ] indexName RENAME TO newIndexName
"," ","
......
...@@ -19,7 +19,6 @@ import java.util.Collections; ...@@ -19,7 +19,6 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
...@@ -311,6 +310,7 @@ public class PgServer implements Service { ...@@ -311,6 +310,7 @@ public class PgServer implements Service {
* @param pretty this flag is ignored * @param pretty this flag is ignored
* @return the SQL statement or the column name * @return the SQL statement or the column name
*/ */
@SuppressWarnings("unused")
public static String getIndexColumn(Connection conn, int indexId, public static String getIndexColumn(Connection conn, int indexId,
Integer ordinalPosition, Boolean pretty) throws SQLException { Integer ordinalPosition, Boolean pretty) throws SQLException {
if (ordinalPosition == null || ordinalPosition.intValue() == 0) { if (ordinalPosition == null || ordinalPosition.intValue() == 0) {
...@@ -438,6 +438,7 @@ public class PgServer implements Service { ...@@ -438,6 +438,7 @@ public class PgServer implements Service {
* @param privilege the privilege to check * @param privilege the privilege to check
* @return true * @return true
*/ */
@SuppressWarnings("unused")
public static boolean hasDatabasePrivilege(int id, String privilege) { public static boolean hasDatabasePrivilege(int id, String privilege) {
return true; return true;
} }
...@@ -450,6 +451,7 @@ public class PgServer implements Service { ...@@ -450,6 +451,7 @@ public class PgServer implements Service {
* @param privilege the privilege to check * @param privilege the privilege to check
* @return true * @return true
*/ */
@SuppressWarnings("unused")
public static boolean hasTablePrivilege(String table, String privilege) { public static boolean hasTablePrivilege(String table, String privilege) {
return true; return true;
} }
...@@ -462,6 +464,7 @@ public class PgServer implements Service { ...@@ -462,6 +464,7 @@ public class PgServer implements Service {
* @param id the id * @param id the id
* @return 1 * @return 1
*/ */
@SuppressWarnings("unused")
public static int getCurrentTid(String table, String id) { public static int getCurrentTid(String table, String id) {
return 1; return 1;
} }
...@@ -475,6 +478,7 @@ public class PgServer implements Service { ...@@ -475,6 +478,7 @@ public class PgServer implements Service {
* @param relationOid the relation object id * @param relationOid the relation object id
* @return always null * @return always null
*/ */
@SuppressWarnings("unused")
public static String getPgExpr(String exprText, int relationOid) { public static String getPgExpr(String exprText, int relationOid) {
return null; return null;
} }
......
...@@ -147,6 +147,7 @@ public class FileStore { ...@@ -147,6 +147,7 @@ public class FileStore {
* *
* @param salt the salt * @param salt the salt
*/ */
@SuppressWarnings("unused")
protected void initKey(byte[] salt) { protected void initKey(byte[] salt) {
// do nothing // do nothing
} }
......
...@@ -254,6 +254,7 @@ public abstract class FilePath { ...@@ -254,6 +254,7 @@ public abstract class FilePath {
* @param inTempDir if the file should be stored in the temporary directory * @param inTempDir if the file should be stored in the temporary directory
* @return the name of the created file * @return the name of the created file
*/ */
@SuppressWarnings("unused")
public FilePath createTempFile(String suffix, boolean deleteOnExit, public FilePath createTempFile(String suffix, boolean deleteOnExit,
boolean inTempDir) throws IOException { boolean inTempDir) throws IOException {
while (true) { while (true) {
......
...@@ -54,7 +54,8 @@ public class LinkSchema { ...@@ -54,7 +54,8 @@ public class LinkSchema {
StringUtils.quoteIdentifier(targetSchema)); StringUtils.quoteIdentifier(targetSchema));
//Workaround for PostgreSQL to avoid index names //Workaround for PostgreSQL to avoid index names
if (url.startsWith("jdbc:postgresql:")) { if (url.startsWith("jdbc:postgresql:")) {
rs = c2.getMetaData().getTables(null, sourceSchema, null, new String[]{"TABLE", "LINKED TABLE", "VIEW", "EXTERNAL"}); rs = c2.getMetaData().getTables(null, sourceSchema, null,
new String[] { "TABLE", "LINKED TABLE", "VIEW", "EXTERNAL" });
} else { } else {
rs = c2.getMetaData().getTables(null, sourceSchema, null, null); rs = c2.getMetaData().getTables(null, sourceSchema, null, null);
} }
......
...@@ -144,7 +144,7 @@ public class RangeTable extends Table { ...@@ -144,7 +144,7 @@ public class RangeTable extends Table {
@Override @Override
public TableType getTableType() { public TableType getTableType() {
throw DbException.throwInternalError(toString()); return TableType.SYSTEM_TABLE;
} }
@Override @Override
......
...@@ -155,6 +155,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -155,6 +155,7 @@ public abstract class Table extends SchemaObjectBase {
* @param key the primary key * @param key the primary key
* @return the row * @return the row
*/ */
@SuppressWarnings("unused")
public Row getRow(Session session, long key) { public Row getRow(Session session, long key) {
return null; return null;
} }
...@@ -189,6 +190,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -189,6 +190,7 @@ public abstract class Table extends SchemaObjectBase {
* @param operation the operation * @param operation the operation
* @param row the row * @param row the row
*/ */
@SuppressWarnings("unused")
public void commit(short operation, Row row) { public void commit(short operation, Row row) {
// nothing to do // nothing to do
} }
...@@ -226,6 +228,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -226,6 +228,7 @@ public abstract class Table extends SchemaObjectBase {
* @param allColumnsSet all columns * @param allColumnsSet all columns
* @return the scan index * @return the scan index
*/ */
@SuppressWarnings("unused")
public Index getScanIndex(Session session, int[] masks, public Index getScanIndex(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder, TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) { HashSet<Column> allColumnsSet) {
...@@ -456,6 +459,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -456,6 +459,7 @@ public abstract class Table extends SchemaObjectBase {
* @param session the session * @param session the session
* @return true if it is * @return true if it is
*/ */
@SuppressWarnings("unused")
public boolean isLockedExclusivelyBy(Session session) { public boolean isLockedExclusivelyBy(Session session) {
return false; return false;
} }
...@@ -1136,6 +1140,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -1136,6 +1140,7 @@ public abstract class Table extends SchemaObjectBase {
* @return an object array with the sessions involved in the deadlock, or * @return an object array with the sessions involved in the deadlock, or
* null * null
*/ */
@SuppressWarnings("unused")
public ArrayList<Session> checkDeadlock(Session session, Session clash, public ArrayList<Session> checkDeadlock(Session session, Session clash,
Set<Session> visited) { Set<Session> visited) {
return null; return null;
......
...@@ -57,6 +57,7 @@ public class TableView extends Table { ...@@ -57,6 +57,7 @@ public class TableView extends Table {
private Query topQuery; private Query topQuery;
private ResultInterface recursiveResult; private ResultInterface recursiveResult;
private boolean tableExpression; private boolean tableExpression;
private boolean isRecursiveQueryDetected;
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,
...@@ -70,12 +71,11 @@ public class TableView extends Table { ...@@ -70,12 +71,11 @@ public class TableView extends Table {
* dependent views. * dependent views.
* *
* @param querySQL the SQL statement * @param querySQL the SQL statement
* @param columnNames the column names
* @param session the session * @param session the session
* @param recursive whether this is a recursive view * @param recursive whether this is a recursive view
* @param force if errors should be ignored * @param force if errors should be ignored
*/ */
public void replace(String querySQL, String[] columnNames, Session session, public void replace(String querySQL, Session session,
boolean recursive, boolean force) { boolean recursive, boolean force) {
String oldQuerySQL = this.querySQL; String oldQuerySQL = this.querySQL;
Column[] oldColumnTemplates = this.columnTemplates; Column[] oldColumnTemplates = this.columnTemplates;
...@@ -94,6 +94,7 @@ public class TableView extends Table { ...@@ -94,6 +94,7 @@ public class TableView extends Table {
this.querySQL = querySQL; this.querySQL = querySQL;
this.columnTemplates = columnTemplates; this.columnTemplates = columnTemplates;
this.recursive = recursive; this.recursive = recursive;
this.isRecursiveQueryDetected = false;
index = new ViewIndex(this, querySQL, params, recursive); index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session); initColumnsAndTables(session);
} }
...@@ -203,9 +204,14 @@ public class TableView extends Table { ...@@ -203,9 +204,14 @@ public class TableView extends Table {
} catch (DbException e) { } catch (DbException e) {
e.addSQL(getCreateSQL()); e.addSQL(getCreateSQL());
createException = e; createException = e;
// if it can't be compiled, then it's a 'zero column table' // If it can't be compiled, then it's a 'zero column table'
// this avoids problems when creating the view when opening the // this avoids problems when creating the view when opening the
// database // database.
// If it can not be compiled - it could also be a recursive common
// table expression query.
if (isRecursiveQueryExceptionDetected(createException)) {
this.isRecursiveQueryDetected = true;
}
tables = New.arrayList(); tables = New.arrayList();
cols = new Column[0]; cols = new Column[0];
if (recursive && columnTemplates != null) { if (recursive && columnTemplates != null) {
...@@ -666,4 +672,29 @@ public class TableView extends Table { ...@@ -666,4 +672,29 @@ public class TableView extends Table {
} }
} }
/**
* Was query recursion detected during compiling.
*
* @return true if yes
*/
public boolean isRecursiveQueryDetected() {
return isRecursiveQueryDetected;
}
/**
* Does exception indicate query recursion?
*/
private boolean isRecursiveQueryExceptionDetected(DbException exception) {
if (exception == null) {
return false;
}
if (exception.getErrorCode() != ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1) {
return false;
}
if (!exception.getMessage().contains("\"" + this.getName() + "\"")) {
return false;
}
return true;
}
} }
...@@ -44,12 +44,9 @@ public class NetUtils { ...@@ -44,12 +44,9 @@ public class NetUtils {
*/ */
public static Socket createLoopbackSocket(int port, boolean ssl) public static Socket createLoopbackSocket(int port, boolean ssl)
throws IOException { throws IOException {
InetAddress address = getBindAddress(); String local = getLocalAddress();
if (address == null) {
address = InetAddress.getLocalHost();
}
try { try {
return createSocket(getHostAddress(address), port, ssl); return createSocket(local, port, ssl);
} catch (IOException e) { } catch (IOException e) {
try { try {
return createSocket("localhost", port, ssl); return createSocket("localhost", port, ssl);
...@@ -60,23 +57,6 @@ public class NetUtils { ...@@ -60,23 +57,6 @@ public class NetUtils {
} }
} }
/**
* Get the host address. This method adds '[' and ']' if required for
* Inet6Address that contain a ':'.
*
* @param address the address
* @return the host address
*/
private static String getHostAddress(InetAddress address) {
String host = address.getHostAddress();
if (address instanceof Inet6Address) {
if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
host = "[" + host + "]";
}
}
return host;
}
/** /**
* Create a client socket that is connected to the given address and port. * Create a client socket that is connected to the given address and port.
* *
...@@ -274,7 +254,21 @@ public class NetUtils { ...@@ -274,7 +254,21 @@ public class NetUtils {
throw DbException.convert(e); throw DbException.convert(e);
} }
} }
String address = bind == null ? "localhost" : getHostAddress(bind); String address;
if (bind == null) {
address = "localhost";
} else {
address = bind.getHostAddress();
if (bind instanceof Inet6Address) {
if (address.indexOf("%") >= 0) {
address = "localhost";
} else if (address.indexOf(':') >= 0 && !address.startsWith("[")) {
// adds'[' and ']' if required for
// Inet6Address that contain a ':'.
address = "[" + address + "]";
}
}
}
if (address.equals("127.0.0.1")) { if (address.equals("127.0.0.1")) {
address = "localhost"; address = "localhost";
} }
......
...@@ -102,7 +102,7 @@ public class Profiler implements Runnable { ...@@ -102,7 +102,7 @@ public class Profiler implements Runnable {
* @param agentArgs the agent arguments * @param agentArgs the agent arguments
* @param inst the instrumentation object * @param inst the instrumentation object
*/ */
public static void premain(String agentArgs, Instrumentation inst) { public static void premain(@SuppressWarnings("unused") String agentArgs, Instrumentation inst) {
instrumentation = inst; instrumentation = inst;
} }
......
...@@ -122,7 +122,7 @@ public class ToChar { ...@@ -122,7 +122,7 @@ public class ToChar {
* @return the formatted number * @return the formatted number
*/ */
public static String toChar(BigDecimal number, String format, public static String toChar(BigDecimal number, String format,
String nlsParam) { @SuppressWarnings("unused") String nlsParam) {
// short-circuit logic for formats that don't follow common logic below // short-circuit logic for formats that don't follow common logic below
String formatUp = format != null ? StringUtils.toUpperEnglish(format) : null; String formatUp = format != null ? StringUtils.toUpperEnglish(format) : null;
...@@ -594,7 +594,7 @@ public class ToChar { ...@@ -594,7 +594,7 @@ public class ToChar {
* @param nlsParam the NLS parameter (if any) * @param nlsParam the NLS parameter (if any)
* @return the formatted timestamp * @return the formatted timestamp
*/ */
public static String toChar(Timestamp ts, String format, String nlsParam) { public static String toChar(Timestamp ts, String format, @SuppressWarnings("unused") String nlsParam) {
if (format == null) { if (format == null) {
format = "DD-MON-YY HH.MI.SS.FF PM"; format = "DD-MON-YY HH.MI.SS.FF PM";
......
...@@ -477,7 +477,7 @@ public abstract class Value { ...@@ -477,7 +477,7 @@ public abstract class Value {
* @param v the value to add * @param v the value to add
* @return the result * @return the result
*/ */
public Value add(Value v) { public Value add(@SuppressWarnings("unused") Value v) {
throw throwUnsupportedExceptionForType("+"); throw throwUnsupportedExceptionForType("+");
} }
...@@ -500,7 +500,7 @@ public abstract class Value { ...@@ -500,7 +500,7 @@ public abstract class Value {
* @param v the value to subtract * @param v the value to subtract
* @return the result * @return the result
*/ */
public Value subtract(Value v) { public Value subtract(@SuppressWarnings("unused") Value v) {
throw throwUnsupportedExceptionForType("-"); throw throwUnsupportedExceptionForType("-");
} }
...@@ -510,7 +510,7 @@ public abstract class Value { ...@@ -510,7 +510,7 @@ public abstract class Value {
* @param v the value to divide by * @param v the value to divide by
* @return the result * @return the result
*/ */
public Value divide(Value v) { public Value divide(@SuppressWarnings("unused") Value v) {
throw throwUnsupportedExceptionForType("/"); throw throwUnsupportedExceptionForType("/");
} }
...@@ -520,7 +520,7 @@ public abstract class Value { ...@@ -520,7 +520,7 @@ public abstract class Value {
* @param v the value to multiply with * @param v the value to multiply with
* @return the result * @return the result
*/ */
public Value multiply(Value v) { public Value multiply(@SuppressWarnings("unused") Value v) {
throw throwUnsupportedExceptionForType("*"); throw throwUnsupportedExceptionForType("*");
} }
...@@ -530,7 +530,7 @@ public abstract class Value { ...@@ -530,7 +530,7 @@ public abstract class Value {
* @param v the value to take the modulus with * @param v the value to take the modulus with
* @return the result * @return the result
*/ */
public Value modulus(Value v) { public Value modulus(@SuppressWarnings("unused") Value v) {
throw throwUnsupportedExceptionForType("%"); throw throwUnsupportedExceptionForType("%");
} }
...@@ -1054,6 +1054,7 @@ public abstract class Value { ...@@ -1054,6 +1054,7 @@ public abstract class Value {
* @param targetScale the requested scale * @param targetScale the requested scale
* @return the value * @return the value
*/ */
@SuppressWarnings("unused")
public Value convertScale(boolean onlyToSmallerScale, int targetScale) { public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
return this; return this;
} }
...@@ -1067,6 +1068,7 @@ public abstract class Value { ...@@ -1067,6 +1068,7 @@ public abstract class Value {
* @param force true if losing numeric precision is allowed * @param force true if losing numeric precision is allowed
* @return the new value * @return the new value
*/ */
@SuppressWarnings("unused")
public Value convertPrecision(long precision, boolean force) { public Value convertPrecision(long precision, boolean force) {
return this; return this;
} }
...@@ -1122,6 +1124,7 @@ public abstract class Value { ...@@ -1122,6 +1124,7 @@ public abstract class Value {
* @param tableId the table where this object is used * @param tableId the table where this object is used
* @return the new value or itself * @return the new value or itself
*/ */
@SuppressWarnings("unused")
public Value copy(DataHandler handler, int tableId) { public Value copy(DataHandler handler, int tableId) {
return this; return this;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
CREATE TABLE VERSION(ID INT PRIMARY KEY, VERSION VARCHAR, CREATED VARCHAR); CREATE TABLE VERSION(ID INT PRIMARY KEY, VERSION VARCHAR, CREATED VARCHAR);
INSERT INTO VERSION VALUES INSERT INTO VERSION VALUES
(146, '1.4.197', '2017-06-10'),
(145, '1.4.195', '2017-04-23'), (145, '1.4.195', '2017-04-23'),
(144, '1.4.194', '2017-03-10'), (144, '1.4.194', '2017-03-10'),
(143, '1.4.193', '2016-10-31'), (143, '1.4.193', '2016-10-31'),
......
...@@ -11,6 +11,7 @@ import java.util.ArrayList; ...@@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.Properties; import java.util.Properties;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.Driver; import org.h2.Driver;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.store.fs.FilePathRec; import org.h2.store.fs.FilePathRec;
...@@ -37,6 +38,7 @@ import org.h2.test.db.TestExclusive; ...@@ -37,6 +38,7 @@ import org.h2.test.db.TestExclusive;
import org.h2.test.db.TestFullText; import org.h2.test.db.TestFullText;
import org.h2.test.db.TestFunctionOverload; import org.h2.test.db.TestFunctionOverload;
import org.h2.test.db.TestFunctions; import org.h2.test.db.TestFunctions;
import org.h2.test.db.TestGeneralCommonTableQueries;
import org.h2.test.db.TestIndex; import org.h2.test.db.TestIndex;
import org.h2.test.db.TestIndexHints; import org.h2.test.db.TestIndexHints;
import org.h2.test.db.TestLargeBlob; import org.h2.test.db.TestLargeBlob;
...@@ -738,6 +740,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -738,6 +740,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestOutOfMemory()); addTest(new TestOutOfMemory());
addTest(new TestReadOnly()); addTest(new TestReadOnly());
addTest(new TestRecursiveQueries()); addTest(new TestRecursiveQueries());
addTest(new TestGeneralCommonTableQueries());
addTest(new TestRights()); addTest(new TestRights());
addTest(new TestRunscript()); addTest(new TestRunscript());
addTest(new TestSQLInjection()); addTest(new TestSQLInjection());
......
...@@ -34,7 +34,6 @@ import java.util.ArrayList; ...@@ -34,7 +34,6 @@ import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.fs.FilePath; import org.h2.store.fs.FilePath;
...@@ -130,6 +129,7 @@ public abstract class TestBase { ...@@ -130,6 +129,7 @@ public abstract class TestBase {
* *
* @param seed the random seed value * @param seed the random seed value
*/ */
@SuppressWarnings("unused")
public void testCase(int seed) throws Exception { public void testCase(int seed) throws Exception {
// do nothing // do nothing
} }
......
...@@ -16,8 +16,8 @@ import java.io.OutputStreamWriter; ...@@ -16,8 +16,8 @@ import java.io.OutputStreamWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import org.h2.test.utils.SelfDestructor; import org.h2.test.utils.SelfDestructor;
import org.h2.util.Task;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Task;
/** /**
* A task that is run as an external process. This class communicates over * A task that is run as an external process. This class communicates over
...@@ -59,7 +59,6 @@ public class TaskProcess { ...@@ -59,7 +59,6 @@ public class TaskProcess {
} }
String[] procDef = new String[list.size()]; String[] procDef = new String[list.size()];
list.toArray(procDef); list.toArray(procDef);
traceOperation("start: " + StringUtils.arrayCombine(procDef, ' '));
process = Runtime.getRuntime().exec(procDef); process = Runtime.getRuntime().exec(procDef);
copyInThread(process.getErrorStream(), System.err); copyInThread(process.getErrorStream(), System.err);
reader = new BufferedReader(new InputStreamReader(process.getInputStream())); reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
...@@ -70,7 +69,6 @@ public class TaskProcess { ...@@ -70,7 +69,6 @@ public class TaskProcess {
"No reply from process, command: " + "No reply from process, command: " +
StringUtils.arrayCombine(procDef, ' ')); StringUtils.arrayCombine(procDef, ' '));
} else if (line.startsWith("running")) { } else if (line.startsWith("running")) {
traceOperation("got reply: " + line);
} else if (line.startsWith("init error")) { } else if (line.startsWith("init error")) {
throw new RuntimeException(line); throw new RuntimeException(line);
} }
...@@ -130,12 +128,4 @@ public class TaskProcess { ...@@ -130,12 +128,4 @@ public class TaskProcess {
process.destroy(); process.destroy();
} }
/**
* Trace the operation. Tracing is disabled by default.
*
* @param s the string to print
*/
private void traceOperation(String s) {
// ignore
}
} }
...@@ -179,7 +179,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -179,7 +179,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
* @param conn the connection * @param conn the connection
* @return a result set * @return a result set
*/ */
public static ResultSet simpleFunctionTable(Connection conn) { public static ResultSet simpleFunctionTable(@SuppressWarnings("unused") Connection conn) {
SimpleResultSet result = new SimpleResultSet(); SimpleResultSet result = new SimpleResultSet();
result.addColumn("A", Types.INTEGER, 0, 0); result.addColumn("A", Types.INTEGER, 0, 0);
result.addColumn("B", Types.CHAR, 0, 0); result.addColumn("B", Types.CHAR, 0, 0);
...@@ -2018,7 +2018,8 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -2018,7 +2018,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
final ResultSet rs = stat.executeQuery( final ResultSet rs = stat.executeQuery(
"select ROUND(-1.2), ROUND(-1.5), ROUND(-1.6), ROUND(2), ROUND(1.5), ROUND(1.8), ROUND(1.1) from dual"); "select ROUND(-1.2), ROUND(-1.5), ROUND(-1.6), " +
"ROUND(2), ROUND(1.5), ROUND(1.8), ROUND(1.1) from dual");
rs.next(); rs.next();
assertEquals(-1, rs.getInt(1)); assertEquals(-1, rs.getInt(1));
...@@ -2258,7 +2259,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -2258,7 +2259,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
* @param conn the connection * @param conn the connection
* @return the result set * @return the result set
*/ */
public static ResultSet nullResultSet(Connection conn) { public static ResultSet nullResultSet(@SuppressWarnings("unused") Connection conn) {
return null; return null;
} }
......
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.test.TestBase;
/**
* Test non-recursive queries using WITH, but more than one common table defined.
*/
public class TestGeneralCommonTableQueries extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public void test() throws Exception {
testSimple();
testImpliedColumnNames();
testChainedQuery();
testParameterizedQuery();
testNumberedParameterizedQuery();
}
private void testSimple() throws Exception {
deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries");
Statement stat;
PreparedStatement prep;
ResultSet rs;
stat = conn.createStatement();
final String simple_two_column_query = "with " +
"t1(n) as (select 1 as first) " +
",t2(n) as (select 2 as first) " +
"select * from t1 union all select * from t2";
rs = stat.executeQuery(simple_two_column_query);
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement(simple_two_column_query);
rs = prep.executeQuery();
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("with " +
"t1(n) as (select 2 as first) " +
",t2(n) as (select 3 as first) " +
"select * from t1 union all select * from t2 where n<>?");
prep.setInt(1, 0); // omit no lines since zero is not in list
rs = prep.executeQuery();
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("with " +
"t1(n) as (select 2 as first) " +
",t2(n) as (select 3 as first) " +
",t3(n) as (select 4 as first) " +
"select * from t1 union all select * from t2 union all select * from t3 where n<>?");
prep.setInt(1, 4); // omit 4 line (last)
rs = prep.executeQuery();
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
assertFalse(rs.next());
conn.close();
deleteDb("commonTableExpressionQueries");
}
private void testImpliedColumnNames() throws Exception {
deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries");
PreparedStatement prep;
ResultSet rs;
prep = conn.prepareStatement("with " +
"t1 as (select 2 as first_col) " +
",t2 as (select first_col+1 from t1) " +
",t3 as (select 4 as first_col) " +
"select * from t1 union all select * from t2 union all select * from t3 where first_col<>?");
prep.setInt(1, 4); // omit 4 line (last)
rs = prep.executeQuery();
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertTrue(rs.next());
assertEquals(3, rs.getInt("FIRST_COL"));
assertFalse(rs.next());
assertEquals(rs.getMetaData().getColumnCount(),1);
assertEquals("FIRST_COL",rs.getMetaData().getColumnLabel(1));
conn.close();
deleteDb("commonTableExpressionQueries");
}
private void testChainedQuery() throws Exception {
deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries");
PreparedStatement prep;
ResultSet rs;
prep = conn.prepareStatement(
" WITH t1 AS (" +
" SELECT 1 AS FIRST_COLUMN" +
")," +
" t2 AS (" +
" SELECT FIRST_COLUMN+1 AS FIRST_COLUMN FROM t1 " +
") " +
"SELECT sum(FIRST_COLUMN) FROM t2");
rs = prep.executeQuery();
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
conn.close();
deleteDb("commonTableExpressionQueries");
}
private void testParameterizedQuery() throws Exception {
deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries");
PreparedStatement prep;
ResultSet rs;
prep = conn.prepareStatement("WITH t1 AS (" +
" SELECT X, 'T1' FROM SYSTEM_RANGE(?,?)" +
")," +
"t2 AS (" +
" SELECT X, 'T2' FROM SYSTEM_RANGE(?,?)" +
") " +
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 " +
"UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(?,?)");
prep.setInt(1, 1);
prep.setInt(2, 2);
prep.setInt(3, 3);
prep.setInt(4, 4);
prep.setInt(5, 5);
prep.setInt(6, 6);
rs = prep.executeQuery();
for(int n: new int[]{1,2,3,4,5,6} ){
assertTrue(rs.next());
assertEquals(n, rs.getInt(1));
}
assertFalse(rs.next());
// call it twice
rs = prep.executeQuery();
for(int n: new int[]{1,2,3,4,5,6} ){
assertTrue(rs.next());
assertEquals(n, rs.getInt(1));
}
assertFalse(rs.next());
conn.close();
deleteDb("commonTableExpressionQueries");
}
private void testNumberedParameterizedQuery() throws Exception {
deleteDb("commonTableExpressionQueries");
Connection conn = getConnection("commonTableExpressionQueries");
PreparedStatement prep;
ResultSet rs;
prep = conn.prepareStatement("WITH t1 AS ("
+" SELECT R.X, 'T1' FROM SYSTEM_RANGE(?1,?2) R"
+"),"
+"t2 AS ("
+" SELECT R.X, 'T2' FROM SYSTEM_RANGE(?3,?4) R"
+") "
+"SELECT * FROM t1 UNION ALL SELECT * FROM t2 UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(?5,?6)");
prep.setInt(1, 1);
prep.setInt(2, 2);
prep.setInt(3, 3);
prep.setInt(4, 4);
prep.setInt(5, 5);
prep.setInt(6, 6);
rs = prep.executeQuery();
for (int n : new int[] { 1, 2, 3, 4, 5, 6 }) {
assertTrue(rs.next());
assertEquals(n, rs.getInt(1));
}
assertEquals("X",rs.getMetaData().getColumnLabel(1));
assertEquals("'T1'",rs.getMetaData().getColumnLabel(2));
assertFalse(rs.next());
conn.close();
deleteDb("commonTableExpressionQueries");
}
}
...@@ -50,6 +50,8 @@ public class TestQueryCache extends TestBase { ...@@ -50,6 +50,8 @@ public class TestQueryCache extends TestBase {
} }
String query = queryBuilder.toString(); String query = queryBuilder.toString();
conn.prepareStatement(query); conn.prepareStatement(query);
int firstGreater = 0;
int firstSmaller = 0;
long time; long time;
ResultSet rs; ResultSet rs;
long first = 0; long first = 0;
...@@ -77,9 +79,17 @@ public class TestQueryCache extends TestBase { ...@@ -77,9 +79,17 @@ public class TestQueryCache extends TestBase {
// try to avoid pauses in subsequent iterations // try to avoid pauses in subsequent iterations
System.gc(); System.gc();
} else if (i > 1001) { } else if (i > 1001) {
assertSmaller(time, first); if (first > time) {
firstGreater++;
} else {
firstSmaller++;
} }
} }
}
// first prepare time must be always greater because of query cache,
// but JVM is too unpredictable to assert that, so just check that
// usually this is true
assertSmaller(firstSmaller, firstGreater);
stat.execute("drop table test"); stat.execute("drop table test");
conn.close(); conn.close();
} }
......
...@@ -13,7 +13,6 @@ import java.sql.PreparedStatement; ...@@ -13,7 +13,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.TestBase; import org.h2.test.TestBase;
/** /**
...@@ -138,7 +137,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -138,7 +137,7 @@ public class TestBatchUpdates extends TestBase {
* @param f the float * @param f the float
* @return the float converted to an int * @return the float converted to an int
*/ */
public static int updatePrices(String message, double f) { public static int updatePrices(@SuppressWarnings("unused") String message, double f) {
return (int) f; return (int) f;
} }
......
...@@ -7,7 +7,9 @@ package org.h2.test.mvcc; ...@@ -7,7 +7,9 @@ package org.h2.test.mvcc;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
...@@ -30,6 +32,7 @@ public class TestMvccMultiThreaded extends TestBase { ...@@ -30,6 +32,7 @@ public class TestMvccMultiThreaded extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
testConcurrentSelectForUpdate();
testMergeWithUniqueKeyViolation(); testMergeWithUniqueKeyViolation();
// not supported currently // not supported currently
if (!config.multiThreaded) { if (!config.multiThreaded) {
...@@ -38,6 +41,50 @@ public class TestMvccMultiThreaded extends TestBase { ...@@ -38,6 +41,50 @@ public class TestMvccMultiThreaded extends TestBase {
} }
} }
private void testConcurrentSelectForUpdate() throws Exception {
deleteDb(getTestName());
Connection conn = getConnection(getTestName() + ";MULTI_THREADED=TRUE");
Statement stat = conn.createStatement();
stat.execute("create table test(id int not null primary key, updated int not null)");
stat.execute("insert into test(id, updated) values(1, 100)");
ArrayList<Task> tasks = new ArrayList<>();
int count = 3;
for (int i = 0; i < count; i++) {
Task task = new Task() {
@Override
public void call() throws Exception {
Connection conn = getConnection(getTestName());
Statement stat = conn.createStatement();
try {
while (!stop) {
try {
stat.execute("select * from test where id=1 for update");
} catch (SQLException e) {
int errorCode = e.getErrorCode();
assertEquals(e.getMessage(),
errorCode == ErrorCode.DEADLOCK_1 ||
errorCode == ErrorCode.LOCK_TIMEOUT_1);
}
}
} finally {
conn.close();
}
}
}.execute();
tasks.add(task);
}
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
ResultSet rs = stat.executeQuery("select * from test");
assertTrue(rs.next());
}
for (Task t : tasks) {
t.get();
}
conn.close();
deleteDb(getTestName());
}
private void testMergeWithUniqueKeyViolation() throws Exception { private void testMergeWithUniqueKeyViolation() throws Exception {
deleteDb(getTestName()); deleteDb(getTestName());
Connection conn = getConnection(getTestName()); Connection conn = getConnection(getTestName());
......
...@@ -2067,6 +2067,7 @@ public class TestMVStore extends TestBase { ...@@ -2067,6 +2067,7 @@ public class TestMVStore extends TestBase {
* *
* @param msg the message * @param msg the message
*/ */
@SuppressWarnings("unused")
protected static void log(String msg) { protected static void log(String msg) {
// System.out.println(msg); // System.out.println(msg);
} }
......
...@@ -88,7 +88,7 @@ public class TestSort extends TestBase { ...@@ -88,7 +88,7 @@ public class TestSort extends TestBase {
* *
* @param type the type of data * @param type the type of data
*/ */
private void test(String type) throws Exception { private void test(@SuppressWarnings("unused") String type) throws Exception {
compareCount.set(0); compareCount.set(0);
// long t = System.nanoTime(); // long t = System.nanoTime();
......
...@@ -18,7 +18,7 @@ public class H2Utils { ...@@ -18,7 +18,7 @@ public class H2Utils {
* @param factory the cursor factory to use * @param factory the cursor factory to use
* @return the database connection * @return the database connection
*/ */
public static H2Database openOrCreateDatabase(String name, int mode, public static H2Database openOrCreateDatabase(String name, @SuppressWarnings("unused") int mode,
H2Database.CursorFactory factory) { H2Database.CursorFactory factory) {
return H2Database.openOrCreateDatabase(name, factory); return H2Database.openOrCreateDatabase(name, factory);
} }
......
...@@ -16,8 +16,8 @@ import java.io.RandomAccessFile; ...@@ -16,8 +16,8 @@ import java.io.RandomAccessFile;
*/ */
public class CheckJavadoc { public class CheckJavadoc {
private static final int MAX_COMMENT_LINE_SIZE = 80; private static final int MAX_COMMENT_LINE_SIZE = 100;
private static final int MAX_SOURCE_LINE_SIZE = 100; private static final int MAX_SOURCE_LINE_SIZE = 120;
private int errorCount; private int errorCount;
/** /**
......
...@@ -17,7 +17,7 @@ import java.util.Arrays; ...@@ -17,7 +17,7 @@ import java.util.Arrays;
*/ */
public class CheckTextFiles { public class CheckTextFiles {
private static final int MAX_SOURCE_LINE_SIZE = 100; private static final int MAX_SOURCE_LINE_SIZE = 120;
// must contain "+" otherwise this here counts as well // must contain "+" otherwise this here counts as well
private static final String COPYRIGHT = "Copyright 2004-2014 " + private static final String COPYRIGHT = "Copyright 2004-2014 " +
......
...@@ -495,7 +495,7 @@ public class XMLParser { ...@@ -495,7 +495,7 @@ public class XMLParser {
* @param name the local name of the attribute * @param name the local name of the attribute
* @return the value or null * @return the value or null
*/ */
public String getAttributeValue(String namespaceURI, String name) { public String getAttributeValue(@SuppressWarnings("unused") String namespaceURI, String name) {
int len = getAttributeCount(); int len = getAttributeCount();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (getAttributeLocalName(i).equals(name)) { if (getAttributeLocalName(i).equals(name)) {
......
...@@ -12,7 +12,7 @@ adapting adaptive add added addiction adding addition additional additionally ...@@ -12,7 +12,7 @@ adapting adaptive add added addiction adding addition additional additionally
additions addon addr address addressed addresses adds adeptia adjacent adjust additions addon addr address addressed addresses adds adeptia adjacent adjust
adjusted adjusts admin administration administrator admins admission ado adopt adjusted adjusts admin administration administrator admins admission ado adopt
advanced advances advantage advantages advised aeiou aejaks aelig aes afaik advanced advances advantage advantages advised aeiou aejaks aelig aes afaik
affect affected affects affero affine after afterwards again against agar age affect affected affects affero affine affinity after afterwards again against agar age
agent agentlib agg aggregate aggregated aggregates aggregating aggressive agile agent agentlib agg aggregate aggregated aggregates aggregating aggressive agile
agrave agree agreeable agreed agreement agreements agrees ahead agrave agree agreeable agreed agreement agreements agrees ahead
ahilmnqbjkcdeopfrsg aid ajax alan alarm ale alefsym alert alessio alexander alfki ahilmnqbjkcdeopfrsg aid ajax alan alarm ale alefsym alert alessio alexander alfki
...@@ -300,7 +300,7 @@ icmpgt icmple icmplt icmpne ico icon iconified icons iconst icu ide idea ideal ...@@ -300,7 +300,7 @@ icmpgt icmple icmplt icmpne ico icon iconified icons iconst icu ide idea ideal
ideas identical identification identified identifier identifiers identify identifying ideas identical identification identified identifier identifiers identify identifying
identities identity idiomatic idiv idle ids idx idxname iee ieee iexcl iface ifeq identities identity idiomatic idiv idle ids idx idxname iee ieee iexcl iface ifeq
ifexists ifge ifgt ifle iflt ifne ifnonnull ifnull iframe ifx ignore ignorecase ignored ifexists ifge ifgt ifle iflt ifne ifnonnull ifnull iframe ifx ignore ignorecase ignored
ignoredriverprivileges ignorelist ignores ignoring igrave iinc ikura ikvm ikvmc ignoredriverprivileges ignorelist ignores ignoring ignite igrave iinc ikura ikvm ikvmc
illegal iload image imageio images imaginary img iml immediately immutable imola imp illegal iload image imageio images imaginary img iml immediately immutable imola imp
impact imperial impersonate impl imple implement implementation implementations impact imperial impersonate impl imple implement implementation implementations
implemented implementing implements implication implicit implicitly implied implemented implementing implements implication implicit implicitly implied
...@@ -315,7 +315,7 @@ indemnified indemnify indemnity indent indentation indentations indented indents ...@@ -315,7 +315,7 @@ indemnified indemnify indemnity indent indentation indentations indented indents
independent independently index indexdef indexed indexer indexers indexes indexid independent independently index indexdef indexed indexer indexers indexes indexid
indexing indicate indicated indicates indicating indication indicator indices indexing indicate indicated indicates indicating indication indicator indices
indirect indirectly individual individually indkey indonesia industries indirect indirectly individual individually indkey indonesia industries
inefficient ineg inet inf infin infinite infinity infix inflate inflater info inefficient ineg inet inf inferred infin infinite infinity infix inflate inflater info
inform information informational informed informix informs informtn infos inform information informational informed informix informs informtn infos
infrastructure infringe infringed infringement infringements infringes infringing infrastructure infringe infringed infringement infringements infringes infringing
inherent inherit inheritance inherited inherits ini init initial initialization inherent inherit inheritance inherited inherits ini init initial initialization
...@@ -434,7 +434,7 @@ obligation obligations observer obsolete obtain obtained obtains obviously ...@@ -434,7 +434,7 @@ obligation obligations observer obsolete obtain obtained obtains obviously
occasionally occupied occupies occupy occur occurred occurrence occurrences occurs occasionally occupied occupies occupy occur occurred occurrence occurrences occurs
ocirc octal octet october octype odbc odbcad odd odg off offending offer offered ocirc octal octet october octype odbc odbcad odd odg off offending offer offered
offering offers office official offline offset offsets often ogc ograve ohloh oid okay offering offers office official offline offset offsets often ogc ograve ohloh oid okay
okra olap olapsys old older oldest oline oliver olivier omega omicron omissions okra olap olapsys old older oldest oline oliver olivier omega omicron omissions omit
omitted omitting once onchange onclick one ones onfocus ongoing onkeydown onkeyup omitted omitting once onchange onclick one ones onfocus ongoing onkeydown onkeyup
online onload only onmousedown onmousemove onmouseout onmouseover onmouseup online onload only onmousedown onmousemove onmouseout onmouseover onmouseup
onreadystatechange onresize onscroll onsubmit onto ontology ontoprise oome oops onreadystatechange onresize onscroll onsubmit onto ontology ontoprise oome oops
...@@ -477,7 +477,7 @@ pointing points poker poland polar pole poleposition policies policy polish poll ...@@ -477,7 +477,7 @@ pointing points poker poland polar pole poleposition policies policy polish poll
polling polski poly polygon pom pondered poodle pool poolable pooled pooling polling polski poly polygon pom pondered poodle pool poolable pooled pooling
pools poor poormans pop popular populate populated population popup port pools poor poormans pop popular populate populated population popup port
portability portable portal portals ported porting portion portions portlet ports portability portable portal portals ported porting portion portions portlet ports
portugal portugu pos position positioned positions positive pospichal possibility portugal portugu pos position positioned positions positional positive pospichal possibility
possible possibly post postal postfix postgre postgres postgresql posting possible possibly post postal postfix postgre postgres postgresql posting
postmaster potential potentially poultry pound pow power powerful poweroff postmaster potential potentially poultry pound pow power powerful poweroff
practicable practice prd pre prec precedence precision precisions predicate practicable practice prd pre prec precedence precision precisions predicate
...@@ -735,3 +735,5 @@ optimisations roughly contractid succeeding tran fixme iters ovain orgid chosen ...@@ -735,3 +735,5 @@ optimisations roughly contractid succeeding tran fixme iters ovain orgid chosen
arbonaut exposing obscure determined turkey buildings indexhints acct arbonaut exposing obscure determined turkey buildings indexhints acct
choosing optimise arte preparator katzyn bla jenkins tot artes pgserver npe choosing optimise arte preparator katzyn bla jenkins tot artes pgserver npe
suffers closeablem mni significance vise identiy vitalus aka ilike uppercasing reentrant suffers closeablem mni significance vise identiy vitalus aka ilike uppercasing reentrant
aff ignite warm upstream producing sfu jit smtm affinity stashed tbl
stumc numbered
...@@ -194,6 +194,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> { ...@@ -194,6 +194,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
* @param value the value * @param value the value
* @return the size * @return the size
*/ */
@SuppressWarnings("unused")
protected int sizeOf(K key, V value) { protected int sizeOf(K key, V value) {
return 1; return 1;
} }
...@@ -204,7 +205,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> { ...@@ -204,7 +205,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
* *
* @param key the key * @param key the key
*/ */
protected void onRemove(K key) { protected void onRemove(@SuppressWarnings("unused") K key) {
// do nothing // do nothing
} }
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
*/ */
package org.h2.jaqu; package org.h2.jaqu;
import static org.h2.jaqu.ValidationRemark.consider;
import static org.h2.jaqu.ValidationRemark.error;
import static org.h2.jaqu.ValidationRemark.warn;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -28,10 +31,6 @@ import org.h2.util.New; ...@@ -28,10 +31,6 @@ import org.h2.util.New;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import static org.h2.jaqu.ValidationRemark.consider;
import static org.h2.jaqu.ValidationRemark.error;
import static org.h2.jaqu.ValidationRemark.warn;
/** /**
* Class to inspect the contents of a particular table including its indexes. * Class to inspect the contents of a particular table including its indexes.
* This class does the bulk of the work in terms of model generation and model * This class does the bulk of the work in terms of model generation and model
...@@ -423,6 +422,7 @@ public class TableInspector { ...@@ -423,6 +422,7 @@ public class TableInspector {
* Validates an inspected index from the database against the * Validates an inspected index from the database against the
* IndexDefinition within the TableDefinition. * IndexDefinition within the TableDefinition.
*/ */
@SuppressWarnings("unused")
private <T> void validate(List<ValidationRemark> remarks, private <T> void validate(List<ValidationRemark> remarks,
TableDefinition<T> def, IndexInspector index, boolean throwError) { TableDefinition<T> def, IndexInspector index, boolean throwError) {
List<IndexDefinition> defIndexes = def.getIndexes(IndexType.STANDARD); List<IndexDefinition> defIndexes = def.getIndexes(IndexType.STANDARD);
......
...@@ -15,6 +15,7 @@ public class PrintStream { ...@@ -15,6 +15,7 @@ public class PrintStream {
* *
* @param s the string * @param s the string
*/ */
@SuppressWarnings("unused")
public void println(String s) { public void println(String s) {
// c: int x = s->chars->length(); // c: int x = s->chars->length();
// c: printf("%.*S\n", x, s->chars->getPointer()); // c: printf("%.*S\n", x, s->chars->getPointer());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论