提交 45a1bba8 authored 作者: andrei's avatar andrei

Merge remote-tracking branch 'h2database/master' into non_blocking

......@@ -21,6 +21,16 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1027: Add support for fully qualified names in MySQL compatibility mode
</li>
<li>Issue #178: INSERT ON DUPLICATE KEY UPDATE returns wrong generated key
</li>
<li>PR #1025: Remove BitField and replace its usages with BitSet
</li>
<li>Issue #1019: Console incorrectly sorts BigDecimal columns alphanumerically
</li>
<li>PR #1021: Update JdbcDatabaseMetaData to JDBC 4.1 (Java 7)
</li>
<li>Issue #992: 1.4.196+ client cannot use DatabaseMetaData with 1.4.195- server
</li>
<li>Issue #1016: ResultSet.getObject() should return enum value, not ordinal
......
......@@ -1232,7 +1232,24 @@ public class Parser {
read("KEY");
read("UPDATE");
do {
Column column = parseColumn(table);
String columnName = readColumnIdentifier();
if (readIf(".")) {
String schemaOrTableName = columnName;
String tableOrColumnName = readColumnIdentifier();
if (readIf(".")) {
if (!table.getSchema().getName().equals(schemaOrTableName)) {
throw DbException.get(ErrorCode.SCHEMA_NAME_MUST_MATCH);
}
columnName = readColumnIdentifier();
} else {
columnName = tableOrColumnName;
tableOrColumnName = schemaOrTableName;
}
if (!table.getName().equals(tableOrColumnName)) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableOrColumnName);
}
}
Column column = table.getColumn(columnName);
read("=");
Expression expression;
if (readIf("DEFAULT")) {
......
......@@ -181,11 +181,15 @@ public class Insert extends Prepared implements ResultTarget {
try {
table.addRow(session, newRow);
} catch (DbException de) {
if (!handleOnDuplicate(de)) {
if (handleOnDuplicate(de)) {
// MySQL returns 2 for updated row
// TODO: detect no-op change
rowNumber++;
} else {
// INSERT IGNORE case
rowNumber--;
continue;
}
continue;
}
generatedKeys.confirmRow(newRow);
session.log(table, UndoLogRecord.INSERT, newRow);
......@@ -399,16 +403,17 @@ public class Insert extends Prepared implements ResultTarget {
}
buff.append(prepareUpdateCondition(foundIndex).getSQL());
String sql = buff.toString();
Prepared command = session.prepare(sql);
Update command = (Update) session.prepare(sql);
command.setUpdateToCurrentValuesReturnsZero(true);
for (Parameter param : command.getParameters()) {
Parameter insertParam = parameters.get(param.getIndex());
param.setValue(insertParam.getValue(session));
}
command.update();
boolean result = command.update() > 0;
for (String variableName : variableNames) {
session.setVariable(variableName, ValueNull.INSTANCE);
}
return true;
return result;
}
private Expression prepareUpdateCondition(Index foundIndex) {
......
......@@ -5,6 +5,7 @@
*/
package org.h2.command.dml;
import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.TimeUnit;
......@@ -13,7 +14,6 @@ import org.h2.expression.Expression;
import org.h2.table.Plan;
import org.h2.table.PlanItem;
import org.h2.table.TableFilter;
import org.h2.util.BitField;
import org.h2.util.Permutations;
/**
......@@ -26,7 +26,7 @@ class Optimizer {
private static final int MAX_BRUTE_FORCE = 2000;
private static final int MAX_GENETIC = 500;
private long startNs;
private BitField switched;
private BitSet switched;
// possible plans for filters, if using brute force:
// 1 filter 1 plan
......@@ -163,13 +163,13 @@ class Optimizer {
}
}
if (generateRandom) {
switched = new BitField();
switched = new BitSet();
System.arraycopy(filters, 0, best, 0, filters.length);
shuffleAll(best);
System.arraycopy(best, 0, list, 0, filters.length);
}
if (testPlan(list)) {
switched = new BitField();
switched = new BitSet();
System.arraycopy(list, 0, best, 0, filters.length);
}
}
......
......@@ -49,6 +49,8 @@ public class Update extends Prepared {
/** The limit expression as specified in the LIMIT clause. */
private Expression limitExpr;
private boolean updateToCurrentValuesReturnsZero;
private final ArrayList<Column> columns = New.arrayList();
private final HashMap<Column, Expression> expressionMap = new HashMap<>();
......@@ -134,7 +136,7 @@ public class Update extends Prepared {
}
newRow.setValue(i, newValue);
}
if (setOnUpdate) {
if (setOnUpdate || updateToCurrentValuesReturnsZero) {
setOnUpdate = false;
for (int i = 0; i < columnCount; i++) {
// Use equals here to detect changes from numeric 0 to 0.0 and similar
......@@ -152,6 +154,8 @@ public class Update extends Prepared {
}
}
}
} else if (updateToCurrentValuesReturnsZero) {
count--;
}
}
table.validateConvertUpdateSequence(session, newRow);
......@@ -268,4 +272,14 @@ public class Update extends Prepared {
public void setSourceTableFilter(TableFilter sourceTableFilter) {
this.sourceTableFilter = sourceTableFilter;
}
/**
* Sets expected update count for update to current values case.
*
* @param updateToCurrentValuesReturnsZero if zero should be returned as update
* count if update set row to current values
*/
public void setUpdateToCurrentValuesReturnsZero(boolean updateToCurrentValuesReturnsZero) {
this.updateToCurrentValuesReturnsZero = updateToCurrentValuesReturnsZero;
}
}
......@@ -8,6 +8,7 @@ package org.h2.engine;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
......@@ -64,7 +65,6 @@ import org.h2.table.TableType;
import org.h2.table.TableView;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server;
import org.h2.util.BitField;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils;
import org.h2.util.NetUtils;
......@@ -123,7 +123,7 @@ public class Database implements DataHandler {
private final Set<Session> userSessions =
Collections.synchronizedSet(new HashSet<Session>());
private final AtomicReference<Session> exclusiveSession = new AtomicReference<>();
private final BitField objectIds = new BitField();
private final BitSet objectIds = new BitSet();
private final Object lobSyncObject = new Object();
private Schema mainSchema;
......@@ -792,7 +792,7 @@ public class Database implements DataHandler {
}
// mark all ids used in the page store
if (pageStore != null) {
BitField f = pageStore.getObjectIds();
BitSet f = pageStore.getObjectIds();
for (int i = 0, len = f.length(); i < len; i++) {
if (f.get(i) && !objectIds.get(i)) {
trace.info("unused object id: " + i);
......
......@@ -22,6 +22,7 @@ import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.BitSet;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
......@@ -29,7 +30,6 @@ import org.h2.api.ErrorCode;
import org.h2.expression.ParameterInterface;
import org.h2.message.DbException;
import org.h2.message.TraceObject;
import org.h2.util.BitField;
import org.h2.value.ValueNull;
/**
......@@ -41,7 +41,7 @@ import org.h2.value.ValueNull;
public class JdbcCallableStatement extends JdbcPreparedStatement implements
CallableStatement, JdbcCallableStatementBackwardsCompat {
private BitField outParameters;
private BitSet outParameters;
private int maxOutParameters;
private HashMap<String, Integer> namedParameters;
......@@ -1637,7 +1637,7 @@ public class JdbcCallableStatement extends JdbcPreparedStatement implements
maxOutParameters = Math.min(
getParameterMetaData().getParameterCount(),
getCheckedMetaData().getColumnCount());
outParameters = new BitField();
outParameters = new BitSet();
}
checkIndexBounds(parameterIndex);
ParameterInterface param = command.getParameters().get(--parameterIndex);
......
......@@ -146,20 +146,19 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of tables in the database. The result set is sorted by
* TABLE_TYPE, TABLE_SCHEM, and TABLE_NAME.
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog </li>
* <li>2 TABLE_SCHEM (String) table schema </li>
* <li>3 TABLE_NAME (String) table name </li>
* <li>4 TABLE_TYPE (String) table type </li>
* <li>5 REMARKS (String) comment </li>
* <li>6 TYPE_CAT (String) always null </li>
* <li>7 TYPE_SCHEM (String) always null </li>
* <li>8 TYPE_NAME (String) always null </li>
* <li>9 SELF_REFERENCING_COL_NAME (String) always null </li>
* <li>10 REF_GENERATION (String) always null </li>
* <li>11 SQL (String) the create table statement or NULL for systems tables
* </li>
* </ul>
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>TABLE_TYPE (String) table type</li>
* <li>REMARKS (String) comment</li>
* <li>TYPE_CAT (String) always null</li>
* <li>TYPE_SCHEM (String) always null</li>
* <li>TYPE_NAME (String) always null</li>
* <li>SELF_REFERENCING_COL_NAME (String) always null</li>
* <li>REF_GENERATION (String) always null</li>
* <li>SQL (String) the create table statement or NULL for systems tables.</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -265,34 +264,33 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of columns. The result set is sorted by TABLE_SCHEM,
* TABLE_NAME, and ORDINAL_POSITION.
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog </li>
* <li>2 TABLE_SCHEM (String) table schema </li>
* <li>3 TABLE_NAME (String) table name </li>
* <li>4 COLUMN_NAME (String) column name </li>
* <li>5 DATA_TYPE (short) data type (see java.sql.Types) </li>
* <li>6 TYPE_NAME (String) data type name ("INTEGER", "VARCHAR",...) </li>
* <li>7 COLUMN_SIZE (int) precision
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>DATA_TYPE (short) data type (see java.sql.Types)</li>
* <li>TYPE_NAME (String) data type name ("INTEGER", "VARCHAR",...)</li>
* <li>COLUMN_SIZE (int) precision
* (values larger than 2 GB are returned as 2 GB)</li>
* <li>8 BUFFER_LENGTH (int) unused </li>
* <li>9 DECIMAL_DIGITS (int) scale (0 for INTEGER and VARCHAR) </li>
* <li>10 NUM_PREC_RADIX (int) radix (always 10) </li>
* <li>11 NULLABLE (int) columnNoNulls or columnNullable</li>
* <li>12 REMARKS (String) comment (always empty) </li>
* <li>13 COLUMN_DEF (String) default value </li>
* <li>14 SQL_DATA_TYPE (int) unused </li>
* <li>15 SQL_DATETIME_SUB (int) unused </li>
* <li>16 CHAR_OCTET_LENGTH (int) unused </li>
* <li>17 ORDINAL_POSITION (int) the column index (1,2,...) </li>
* <li>18 IS_NULLABLE (String) "NO" or "YES" </li>
* <li>19 SCOPE_CATALOG (String) always null </li>
* <li>20 SCOPE_SCHEMA (String) always null </li>
* <li>21 SCOPE_TABLE (String) always null </li>
* <li>22 SOURCE_DATA_TYPE (short) null </li>
* <li>23 IS_AUTOINCREMENT (String) "NO" or "YES" </li>
* <li>24 SCOPE_CATLOG (String) always null (the typo is on purpose,
* for compatibility with the JDBC specification prior to 4.1)</li>
* </ul>
* <li>BUFFER_LENGTH (int) unused</li>
* <li>DECIMAL_DIGITS (int) scale (0 for INTEGER and VARCHAR)</li>
* <li>NUM_PREC_RADIX (int) radix (always 10)</li>
* <li>NULLABLE (int) columnNoNulls or columnNullable</li>
* <li>REMARKS (String) comment (always empty)</li>
* <li>COLUMN_DEF (String) default value</li>
* <li>SQL_DATA_TYPE (int) unused</li>
* <li>SQL_DATETIME_SUB (int) unused</li>
* <li>CHAR_OCTET_LENGTH (int) unused</li>
* <li>ORDINAL_POSITION (int) the column index (1,2,...)</li>
* <li>IS_NULLABLE (String) "NO" or "YES"</li>
* <li>SCOPE_CATALOG (String) always null</li>
* <li>SCOPE_SCHEMA (String) always null</li>
* <li>SCOPE_TABLE (String) always null</li>
* <li>SOURCE_DATA_TYPE (short) null</li>
* <li>IS_AUTOINCREMENT (String) "NO" or "YES"</li>
* <li>IS_GENERATEDCOLUMN (String) "NO" or "YES"</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -344,7 +342,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements
+ "SCOPE_TABLE, "
+ "SOURCE_DATA_TYPE, "
+ "IS_AUTOINCREMENT, "
+ "SCOPE_CATLOG "
+ "IS_GENERATEDCOLUMN "
+ "FROM ("
+ "SELECT "
+ "s.SYNONYM_CATALOG TABLE_CAT, "
......@@ -371,7 +369,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements
+ "c.SOURCE_DATA_TYPE, "
+ "CASE WHEN c.SEQUENCE_NAME IS NULL THEN "
+ "CAST(?1 AS VARCHAR) ELSE CAST(?2 AS VARCHAR) END IS_AUTOINCREMENT, "
+ "CAST(c.SOURCE_DATA_TYPE AS VARCHAR) SCOPE_CATLOG "
+ "CASE WHEN c.IS_COMPUTED THEN "
+ "CAST(?2 AS VARCHAR) ELSE CAST(?1 AS VARCHAR) END IS_GENERATEDCOLUMN "
+ "FROM INFORMATION_SCHEMA.COLUMNS c JOIN INFORMATION_SCHEMA.SYNONYMS s ON "
+ "s.SYNONYM_FOR = c.TABLE_NAME "
+ "AND s.SYNONYM_FOR_SCHEMA = c.TABLE_SCHEMA "
......@@ -406,7 +405,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements
+ "SOURCE_DATA_TYPE, "
+ "CASE WHEN SEQUENCE_NAME IS NULL THEN "
+ "CAST(?1 AS VARCHAR) ELSE CAST(?2 AS VARCHAR) END IS_AUTOINCREMENT, "
+ "CAST(SOURCE_DATA_TYPE AS VARCHAR) SCOPE_CATLOG "
+ "CASE WHEN IS_COMPUTED THEN "
+ "CAST(?2 AS VARCHAR) ELSE CAST(?1 AS VARCHAR) END IS_GENERATEDCOLUMN "
+ "FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE TABLE_CATALOG LIKE ?3 ESCAPE ?7 "
+ "AND TABLE_SCHEMA LIKE ?4 ESCAPE ?7 "
......@@ -436,23 +436,23 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* is sorted by NON_UNIQUE ('false' first), TYPE, TABLE_SCHEM, INDEX_NAME,
* and ORDINAL_POSITION.
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog </li>
* <li>2 TABLE_SCHEM (String) table schema </li>
* <li>3 TABLE_NAME (String) table name </li>
* <li>4 NON_UNIQUE (boolean) 'true' if non-unique</li>
* <li>5 INDEX_QUALIFIER (String) index catalog </li>
* <li>6 INDEX_NAME (String) index name </li>
* <li>7 TYPE (short) the index type (always tableIndexOther) </li>
* <li>8 ORDINAL_POSITION (short) column index (1, 2, ...) </li>
* <li>9 COLUMN_NAME (String) column name </li>
* <li>10 ASC_OR_DESC (String) ascending or descending (always 'A') </li>
* <li>11 CARDINALITY (int) numbers of unique values </li>
* <li>12 PAGES (int) number of pages use (always 0) </li>
* <li>13 FILTER_CONDITION (String) filter condition (always empty) </li>
* <li>14 SORT_TYPE (int) the sort type bit map: 1=DESCENDING,
* 2=NULLS_FIRST, 4=NULLS_LAST </li>
* </ul>
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>NON_UNIQUE (boolean) 'true' if non-unique</li>
* <li>INDEX_QUALIFIER (String) index catalog</li>
* <li>INDEX_NAME (String) index name</li>
* <li>TYPE (short) the index type (always tableIndexOther)</li>
* <li>ORDINAL_POSITION (short) column index (1, 2, ...)</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>ASC_OR_DESC (String) ascending or descending (always 'A')</li>
* <li>CARDINALITY (int) numbers of unique values</li>
* <li>PAGES (int) number of pages use (always 0)</li>
* <li>FILTER_CONDITION (String) filter condition (always empty)</li>
* <li>SORT_TYPE (int) the sort type bit map: 1=DESCENDING,
* 2=NULLS_FIRST, 4=NULLS_LAST</li>
* </ol>
*
* @param catalogPattern null or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -517,14 +517,14 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the primary key columns for a table. The result set is sorted by
* TABLE_SCHEM, and COLUMN_NAME (and not by KEY_SEQ).
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog</li>
* <li>2 TABLE_SCHEM (String) table schema</li>
* <li>3 TABLE_NAME (String) table name</li>
* <li>4 COLUMN_NAME (String) column name</li>
* <li>5 KEY_SEQ (short) the column index of this column (1,2,...)</li>
* <li>6 PK_NAME (String) the name of the primary key index</li>
* </ul>
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>KEY_SEQ (short) the column index of this column (1,2,...)</li>
* <li>PK_NAME (String) the name of the primary key index</li>
* </ol>
*
* @param catalogPattern null or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -700,18 +700,18 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* procedures with the same name, each with a different number of input
* parameters.
*
* <ul>
* <li>1 PROCEDURE_CAT (String) catalog </li>
* <li>2 PROCEDURE_SCHEM (String) schema </li>
* <li>3 PROCEDURE_NAME (String) name </li>
* <li>4 NUM_INPUT_PARAMS (int) the number of arguments </li>
* <li>5 NUM_OUTPUT_PARAMS (int) for future use, always 0 </li>
* <li>6 NUM_RESULT_SETS (int) for future use, always 0 </li>
* <li>7 REMARKS (String) description </li>
* <li>8 PROCEDURE_TYPE (short) if this procedure returns a result
* (procedureNoResult or procedureReturnsResult) </li>
* <li>9 SPECIFIC_NAME (String) name </li>
* </ul>
* <ol>
* <li>PROCEDURE_CAT (String) catalog</li>
* <li>PROCEDURE_SCHEM (String) schema</li>
* <li>PROCEDURE_NAME (String) name</li>
* <li>NUM_INPUT_PARAMS (int) the number of arguments</li>
* <li>NUM_OUTPUT_PARAMS (int) for future use, always 0</li>
* <li>NUM_RESULT_SETS (int) for future use, always 0</li>
* <li>REMARKS (String) description</li>
* <li>PROCEDURE_TYPE (short) if this procedure returns a result
* (procedureNoResult or procedureReturnsResult)</li>
* <li>SPECIFIC_NAME (String) name</li>
* </ol>
*
* @param catalogPattern null or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -764,32 +764,32 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* There are potentially multiple procedures with the same name, each with a
* different number of input parameters.
*
* <ul>
* <li>1 PROCEDURE_CAT (String) catalog </li>
* <li>2 PROCEDURE_SCHEM (String) schema </li>
* <li>3 PROCEDURE_NAME (String) name </li>
* <li>4 COLUMN_NAME (String) column name </li>
* <li>5 COLUMN_TYPE (short) column type
* <ol>
* <li>PROCEDURE_CAT (String) catalog</li>
* <li>PROCEDURE_SCHEM (String) schema</li>
* <li>PROCEDURE_NAME (String) name</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>COLUMN_TYPE (short) column type
* (always DatabaseMetaData.procedureColumnIn)</li>
* <li>6 DATA_TYPE (short) sql type </li>
* <li>7 TYPE_NAME (String) type name </li>
* <li>8 PRECISION (int) precision </li>
* <li>9 LENGTH (int) length </li>
* <li>10 SCALE (short) scale </li>
* <li>11 RADIX (int) always 10 </li>
* <li>12 NULLABLE (short) nullable
* <li>DATA_TYPE (short) sql type</li>
* <li>TYPE_NAME (String) type name</li>
* <li>PRECISION (int) precision</li>
* <li>LENGTH (int) length</li>
* <li>SCALE (short) scale</li>
* <li>RADIX (int) always 10</li>
* <li>NULLABLE (short) nullable
* (DatabaseMetaData.columnNoNulls for primitive data types,
* DatabaseMetaData.columnNullable otherwise)</li>
* <li>13 REMARKS (String) description </li>
* <li>14 COLUMN_DEF (String) always null </li>
* <li>15 SQL_DATA_TYPE (int) for future use, always 0 </li>
* <li>16 SQL_DATETIME_SUB (int) for future use, always 0 </li>
* <li>17 CHAR_OCTET_LENGTH (int) always null </li>
* <li>18 ORDINAL_POSITION (int) the parameter index
* starting from 1 (0 is the return value) </li>
* <li>19 IS_NULLABLE (String) always "YES" </li>
* <li>20 SPECIFIC_NAME (String) name </li>
* </ul>
* <li>REMARKS (String) description</li>
* <li>COLUMN_DEF (String) always null</li>
* <li>SQL_DATA_TYPE (int) for future use, always 0</li>
* <li>SQL_DATETIME_SUB (int) for future use, always 0</li>
* <li>CHAR_OCTET_LENGTH (int) always null</li>
* <li>ORDINAL_POSITION (int) the parameter index
* starting from 1 (0 is the return value)</li>
* <li>IS_NULLABLE (String) always "YES"</li>
* <li>SPECIFIC_NAME (String) name</li>
* </ol>
*
* @param catalogPattern null or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -858,11 +858,11 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of schemas.
* The result set is sorted by TABLE_SCHEM.
*
* <ul>
* <li>1 TABLE_SCHEM (String) schema name
* </li><li>2 TABLE_CATALOG (String) catalog name
* </li><li>3 IS_DEFAULT (boolean) if this is the default schema
* </li></ul>
* <ol>
* <li>TABLE_SCHEM (String) schema name</li>
* <li>TABLE_CATALOG (String) catalog name</li>
* <li>IS_DEFAULT (boolean) if this is the default schema</li>
* </ol>
*
* @return the schema list
* @throws SQLException if the connection is closed
......@@ -889,9 +889,9 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of catalogs.
* The result set is sorted by TABLE_CAT.
*
* <ul>
* <li>1 TABLE_CAT (String) catalog name
* </li></ul>
* <ol>
* <li>TABLE_CAT (String) catalog name</li>
* </ol>
*
* @return the catalog list
* @throws SQLException if the connection is closed
......@@ -913,9 +913,9 @@ public class JdbcDatabaseMetaData extends TraceObject implements
/**
* Gets the list of table types. This call returns a result set with five
* records: "SYSTEM TABLE", "TABLE", "VIEW", "TABLE LINK" and "EXTERNAL".
* <ul>
* <li>1 TABLE_TYPE (String) table type
* </li></ul>
* <ol>
* <li>TABLE_TYPE (String) table type</li>
* </ol>
*
* @return the table types
* @throws SQLException if the connection is closed
......@@ -939,18 +939,18 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of column privileges. The result set is sorted by
* COLUMN_NAME and PRIVILEGE
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog</li>
* <li>2 TABLE_SCHEM (String) table schema</li>
* <li>3 TABLE_NAME (String) table name</li>
* <li>4 COLUMN_NAME (String) column name</li>
* <li>5 GRANTOR (String) grantor of access</li>
* <li>6 GRANTEE (String) grantee of access</li>
* <li>7 PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>GRANTOR (String) grantor of access</li>
* <li>GRANTEE (String) grantee of access</li>
* <li>PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
* (only one per row)</li>
* <li>8 IS_GRANTABLE (String) YES means the grantee can grant access to
* <li>IS_GRANTABLE (String) YES means the grantee can grant access to
* others</li>
* </ul>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -1006,17 +1006,17 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of table privileges. The result set is sorted by
* TABLE_SCHEM, TABLE_NAME, and PRIVILEGE.
*
* <ul>
* <li>1 TABLE_CAT (String) table catalog </li>
* <li>2 TABLE_SCHEM (String) table schema </li>
* <li>3 TABLE_NAME (String) table name </li>
* <li>4 GRANTOR (String) grantor of access </li>
* <li>5 GRANTEE (String) grantee of access </li>
* <li>6 PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
* (only one per row) </li>
* <li>7 IS_GRANTABLE (String) YES means the grantee can grant access to
* others </li>
* </ul>
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>GRANTOR (String) grantor of access</li>
* <li>GRANTEE (String) grantee of access</li>
* <li>PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
* (only one per row)</li>
* <li>IS_GRANTABLE (String) YES means the grantee can grant access to
* others</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -1066,17 +1066,17 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of columns that best identifier a row in a table.
* The list is ordered by SCOPE.
*
* <ul>
* <li>1 SCOPE (short) scope of result (always bestRowSession)
* </li><li>2 COLUMN_NAME (String) column name
* </li><li>3 DATA_TYPE (short) SQL data type, see also java.sql.Types
* </li><li>4 TYPE_NAME (String) type name
* </li><li>5 COLUMN_SIZE (int) precision
* (values larger than 2 GB are returned as 2 GB)
* </li><li>6 BUFFER_LENGTH (int) unused
* </li><li>7 DECIMAL_DIGITS (short) scale
* </li><li>8 PSEUDO_COLUMN (short) (always bestRowNotPseudo)
* </li></ul>
* <ol>
* <li>SCOPE (short) scope of result (always bestRowSession)</li>
* <li>COLUMN_NAME (String) column name</li>
* <li>DATA_TYPE (short) SQL data type, see also java.sql.Types</li>
* <li>TYPE_NAME (String) type name</li>
* <li>COLUMN_SIZE (int) precision
* (values larger than 2 GB are returned as 2 GB)</li>
* <li>BUFFER_LENGTH (int) unused</li>
* <li>DECIMAL_DIGITS (short) scale</li>
* <li>PSEUDO_COLUMN (short) (always bestRowNotPseudo)</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -1137,17 +1137,17 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Get the list of columns that are update when any value is updated.
* The result set is always empty.
*
* <ul>
* <li>1 SCOPE (int) not used
* </li><li>2 COLUMN_NAME (String) column name
* </li><li>3 DATA_TYPE (int) SQL data type - see also java.sql.Types
* </li><li>4 TYPE_NAME (String) data type name
* </li><li>5 COLUMN_SIZE (int) precision
* (values larger than 2 GB are returned as 2 GB)
* </li><li>6 BUFFER_LENGTH (int) length (bytes)
* </li><li>7 DECIMAL_DIGITS (int) scale
* </li><li>8 PSEUDO_COLUMN (int) is this column a pseudo column
* </li></ul>
* <ol>
* <li>1 SCOPE (int) not used</li>
* <li>2 COLUMN_NAME (String) column name</li>
* <li>3 DATA_TYPE (int) SQL data type - see also java.sql.Types</li>
* <li>4 TYPE_NAME (String) data type name</li>
* <li>5 COLUMN_SIZE (int) precision
* (values larger than 2 GB are returned as 2 GB)</li>
* <li>6 BUFFER_LENGTH (int) length (bytes)</li>
* <li>7 DECIMAL_DIGITS (int) scale</li>
* <li>8 PSEUDO_COLUMN (int) is this column a pseudo column</li>
* </ol>
*
* @param catalog null (to get all objects) or the catalog name
* @param schema null (to get all objects) or a schema name
......@@ -1188,25 +1188,25 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* result set is sorted by PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
* FK_NAME, KEY_SEQ.
*
* <ul>
* <li>1 PKTABLE_CAT (String) primary catalog </li>
* <li>2 PKTABLE_SCHEM (String) primary schema </li>
* <li>3 PKTABLE_NAME (String) primary table </li>
* <li>4 PKCOLUMN_NAME (String) primary column </li>
* <li>5 FKTABLE_CAT (String) foreign catalog </li>
* <li>6 FKTABLE_SCHEM (String) foreign schema </li>
* <li>7 FKTABLE_NAME (String) foreign table </li>
* <li>8 FKCOLUMN_NAME (String) foreign column </li>
* <li>9 KEY_SEQ (short) sequence number (1, 2, ...) </li>
* <li>10 UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...) </li>
* <li>11 DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...) </li>
* <li>12 FK_NAME (String) foreign key name </li>
* <li>13 PK_NAME (String) primary key name </li>
* <li>14 DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable) </li>
* </ul>
* <ol>
* <li>PKTABLE_CAT (String) primary catalog</li>
* <li>PKTABLE_SCHEM (String) primary schema</li>
* <li>PKTABLE_NAME (String) primary table</li>
* <li>PKCOLUMN_NAME (String) primary column</li>
* <li>FKTABLE_CAT (String) foreign catalog</li>
* <li>FKTABLE_SCHEM (String) foreign schema</li>
* <li>FKTABLE_NAME (String) foreign table</li>
* <li>FKCOLUMN_NAME (String) foreign column</li>
* <li>KEY_SEQ (short) sequence number (1, 2, ...)</li>
* <li>UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...)</li>
* <li>DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...)</li>
* <li>FK_NAME (String) foreign key name</li>
* <li>PK_NAME (String) primary key name</li>
* <li>DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable)</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern the schema name of the foreign table
......@@ -1261,25 +1261,25 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* set is sorted by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME,
* KEY_SEQ.
*
* <ul>
* <li>1 PKTABLE_CAT (String) primary catalog </li>
* <li>2 PKTABLE_SCHEM (String) primary schema </li>
* <li>3 PKTABLE_NAME (String) primary table </li>
* <li>4 PKCOLUMN_NAME (String) primary column </li>
* <li>5 FKTABLE_CAT (String) foreign catalog </li>
* <li>6 FKTABLE_SCHEM (String) foreign schema </li>
* <li>7 FKTABLE_NAME (String) foreign table </li>
* <li>8 FKCOLUMN_NAME (String) foreign column </li>
* <li>9 KEY_SEQ (short) sequence number (1,2,...) </li>
* <li>10 UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...) </li>
* <li>11 DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...) </li>
* <li>12 FK_NAME (String) foreign key name </li>
* <li>13 PK_NAME (String) primary key name </li>
* <li>14 DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable) </li>
* </ul>
* <ol>
* <li>PKTABLE_CAT (String) primary catalog</li>
* <li>PKTABLE_SCHEM (String) primary schema</li>
* <li>PKTABLE_NAME (String) primary table</li>
* <li>PKCOLUMN_NAME (String) primary column</li>
* <li>FKTABLE_CAT (String) foreign catalog</li>
* <li>FKTABLE_SCHEM (String) foreign schema</li>
* <li>FKTABLE_NAME (String) foreign table</li>
* <li>FKCOLUMN_NAME (String) foreign column</li>
* <li>KEY_SEQ (short) sequence number (1,2,...)</li>
* <li>UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...)</li>
* <li>DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...)</li>
* <li>FK_NAME (String) foreign key name</li>
* <li>PK_NAME (String) primary key name</li>
* <li>DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable)</li>
* </ol>
*
* @param catalogPattern null or the catalog name
* @param schemaPattern the schema name of the primary table
......@@ -1335,25 +1335,25 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* result set is sorted by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME,
* FK_NAME, KEY_SEQ.
*
* <ul>
* <li>1 PKTABLE_CAT (String) primary catalog </li>
* <li>2 PKTABLE_SCHEM (String) primary schema </li>
* <li>3 PKTABLE_NAME (String) primary table </li>
* <li>4 PKCOLUMN_NAME (String) primary column </li>
* <li>5 FKTABLE_CAT (String) foreign catalog </li>
* <li>6 FKTABLE_SCHEM (String) foreign schema </li>
* <li>7 FKTABLE_NAME (String) foreign table </li>
* <li>8 FKCOLUMN_NAME (String) foreign column </li>
* <li>9 KEY_SEQ (short) sequence number (1,2,...) </li>
* <li>10 UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...) </li>
* <li>11 DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...) </li>
* <li>12 FK_NAME (String) foreign key name </li>
* <li>13 PK_NAME (String) primary key name </li>
* <li>14 DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable) </li>
* </ul>
* <ol>
* <li>PKTABLE_CAT (String) primary catalog</li>
* <li>PKTABLE_SCHEM (String) primary schema</li>
* <li>PKTABLE_NAME (String) primary table</li>
* <li>PKCOLUMN_NAME (String) primary column</li>
* <li>FKTABLE_CAT (String) foreign catalog</li>
* <li>FKTABLE_SCHEM (String) foreign schema</li>
* <li>FKTABLE_NAME (String) foreign table</li>
* <li>FKCOLUMN_NAME (String) foreign column</li>
* <li>KEY_SEQ (short) sequence number (1,2,...)</li>
* <li>UPDATE_RULE (short) action on update (see
* DatabaseMetaData.importedKey...)</li>
* <li>DELETE_RULE (short) action on delete (see
* DatabaseMetaData.importedKey...)</li>
* <li>FK_NAME (String) foreign key name</li>
* <li>PK_NAME (String) primary key name</li>
* <li>DEFERRABILITY (short) deferrable or not (always
* importedKeyNotDeferrable)</li>
* </ol>
*
* @param primaryCatalogPattern null or the catalog name
* @param primarySchemaPattern the schema name of the primary table
......@@ -1424,15 +1424,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of user-defined data types.
* This call returns an empty result set.
*
* <ul>
* <li>1 TYPE_CAT (String) catalog
* </li><li>2 TYPE_SCHEM (String) schema
* </li><li>3 TYPE_NAME (String) type name
* </li><li>4 CLASS_NAME (String) Java class
* </li><li>5 DATA_TYPE (short) SQL Type - see also java.sql.Types
* </li><li>6 REMARKS (String) description
* </li><li>7 BASE_TYPE (short) base type - see also java.sql.Types
* </li></ul>
* <ol>
* <li>TYPE_CAT (String) catalog</li>
* <li>TYPE_SCHEM (String) schema</li>
* <li>TYPE_NAME (String) type name</li>
* <li>CLASS_NAME (String) Java class</li>
* <li>DATA_TYPE (short) SQL Type - see also java.sql.Types</li>
* <li>REMARKS (String) description</li>
* <li>BASE_TYPE (short) base type - see also java.sql.Types</li>
* </ol>
*
* @param catalog ignored
* @param schemaPattern ignored
......@@ -1473,27 +1473,26 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* afterwards by how closely the data type maps to the corresponding JDBC
* SQL type (best match first).
*
* <ul>
* <li>1 TYPE_NAME (String) type name </li>
* <li>2 DATA_TYPE (short) SQL data type - see also java.sql.Types </li>
* <li>3 PRECISION (int) maximum precision </li>
* <li>4 LITERAL_PREFIX (String) prefix used to quote a literal </li>
* <li>5 LITERAL_SUFFIX (String) suffix used to quote a literal </li>
* <li>6 CREATE_PARAMS (String) parameters used (may be null) </li>
* <li>7 NULLABLE (short) typeNoNulls (NULL not allowed) or typeNullable
* </li>
* <li>8 CASE_SENSITIVE (boolean) case sensitive </li>
* <li>9 SEARCHABLE (short) typeSearchable </li>
* <li>10 UNSIGNED_ATTRIBUTE (boolean) unsigned </li>
* <li>11 FIXED_PREC_SCALE (boolean) fixed precision </li>
* <li>12 AUTO_INCREMENT (boolean) auto increment </li>
* <li>13 LOCAL_TYPE_NAME (String) localized version of the data type </li>
* <li>14 MINIMUM_SCALE (short) minimum scale </li>
* <li>15 MAXIMUM_SCALE (short) maximum scale </li>
* <li>16 SQL_DATA_TYPE (int) unused </li>
* <li>17 SQL_DATETIME_SUB (int) unused </li>
* <li>18 NUM_PREC_RADIX (int) 2 for binary, 10 for decimal </li>
* </ul>
* <ol>
* <li>TYPE_NAME (String) type name</li>
* <li>DATA_TYPE (short) SQL data type - see also java.sql.Types</li>
* <li>PRECISION (int) maximum precision</li>
* <li>LITERAL_PREFIX (String) prefix used to quote a literal</li>
* <li>LITERAL_SUFFIX (String) suffix used to quote a literal</li>
* <li>CREATE_PARAMS (String) parameters used (may be null)</li>
* <li>NULLABLE (short) typeNoNulls (NULL not allowed) or typeNullable</li>
* <li>CASE_SENSITIVE (boolean) case sensitive</li>
* <li>SEARCHABLE (short) typeSearchable</li>
* <li>UNSIGNED_ATTRIBUTE (boolean) unsigned</li>
* <li>FIXED_PREC_SCALE (boolean) fixed precision</li>
* <li>AUTO_INCREMENT (boolean) auto increment</li>
* <li>LOCAL_TYPE_NAME (String) localized version of the data type</li>
* <li>MINIMUM_SCALE (short) minimum scale</li>
* <li>MAXIMUM_SCALE (short) maximum scale</li>
* <li>SQL_DATA_TYPE (int) unused</li>
* <li>SQL_DATETIME_SUB (int) unused</li>
* <li>NUM_PREC_RADIX (int) 2 for binary, 10 for decimal</li>
* </ol>
*
* @return the list of data types
* @throws SQLException if the connection is closed
......@@ -2946,12 +2945,12 @@ public class JdbcDatabaseMetaData extends TraceObject implements
/**
* Get the list of super tables of a table. This method currently returns an
* empty result set.
* <ul>
* <li>1 TABLE_CAT (String) table catalog</li>
* <li>2 TABLE_SCHEM (String) table schema</li>
* <li>3 TABLE_NAME (String) table name</li>
* <li>4 SUPERTABLE_NAME (String) the name of the super table</li>
* </ul>
* <ol>
* <li>TABLE_CAT (String) table catalog</li>
* <li>TABLE_SCHEM (String) table schema</li>
* <li>TABLE_NAME (String) table name</li>
* <li>SUPERTABLE_NAME (String) the name of the super table</li>
* </ol>
*
* @param catalog null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......@@ -3054,12 +3053,12 @@ public class JdbcDatabaseMetaData extends TraceObject implements
/**
* Gets the minor version of the supported JDBC API.
*
* @return the minor version (0)
* @return the minor version (1)
*/
@Override
public int getJDBCMinorVersion() {
debugCodeCall("getJDBCMinorVersion");
return 0;
return 1;
}
/**
......@@ -3132,11 +3131,11 @@ public class JdbcDatabaseMetaData extends TraceObject implements
* Gets the list of schemas in the database.
* The result set is sorted by TABLE_SCHEM.
*
* <ul>
* <li>1 TABLE_SCHEM (String) schema name
* </li><li>2 TABLE_CATALOG (String) catalog name
* </li><li>3 IS_DEFAULT (boolean) if this is the default schema
* </li></ul>
* <ol>
* <li>TABLE_SCHEM (String) schema name</li>
* <li>TABLE_CATALOG (String) catalog name</li>
* <li>IS_DEFAULT (boolean) if this is the default schema</li>
* </ol>
*
* @param catalogPattern null (to get all objects) or the catalog name
* @param schemaPattern null (to get all objects) or a schema name
......
......@@ -9,6 +9,7 @@ import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -33,7 +34,6 @@ import org.h2.store.InDoubtTransaction;
import org.h2.store.fs.FileChannelInputStream;
import org.h2.store.fs.FileUtils;
import org.h2.table.TableBase;
import org.h2.util.BitField;
import org.h2.util.New;
/**
......@@ -263,7 +263,7 @@ public class MVTableEngine implements TableEngine {
*
* @param objectIds the ids of the objects to keep
*/
public void removeTemporaryMaps(BitField objectIds) {
public void removeTemporaryMaps(BitSet objectIds) {
for (String mapName : store.getMapNames()) {
if (mapName.startsWith("temp.")) {
MVMap<?, ?> map = store.openMap(mapName);
......
......@@ -163,6 +163,10 @@ function getInnerText(el) {
return str;
}
function isNullCell(td) {
return td.childNodes.length == 1 && (td.childNodes[0].nodeName == "I");
}
function resortTable(link) {
// get the span
var span;
......@@ -175,26 +179,39 @@ function resortTable(link) {
var td = link.parentNode;
var column = td.cellIndex;
var table = getParent(td,'TABLE');
if (table.rows.length <= 1) return;
var rows = table.rows;
if (rows.length <= 1) return;
// detect sort type
var sortNumeric = false;
var x = getInnerText(table.rows[1].cells[column]);
if (x.match(/^[\d\.]+$/)) {
sortNumeric = true;
var sortNumeric = true;
for (i = 1; i < rows.length; i++) {
var td = rows[i].cells[column];
if (!isNullCell(td)) {
var x = getInnerText(td);
// H2 does not return numeric values with leading +, but may return
// values in scientific notation
if (!x.match(/^\-?\d*\.?\d+(?:[Ee][\+\-]?\d+)?$/)) {
sortNumeric = false;
break;
}
}
}
var newRows = new Array();
var rows = table.rows;
for (i=1; i<rows.length; i++) {
var o = new Object();
o.data = rows[i];
o.id = i;
if (sortNumeric) {
o.sort = parseFloat(getInnerText(o.data.cells[column]));
if (isNaN(o.sort)) o.sort = 0;
} else {
o.sort = getInnerText(o.data.cells[column]);
var td = o.data.cells[column];
var n = isNullCell(td);
o.isNull = n;
if (!n) {
var txt = getInnerText(td);
if (sortNumeric) {
o.sort = parseFloat(txt);
if (isNaN(o.sort)) o.sort = 0;
} else {
o.sort = txt;
}
}
newRows[i-1] = o;
}
......@@ -240,6 +257,10 @@ function getParent(el, pTagName) {
}
function sortCallback(ra, rb) {
if (ra.isNull) {
return rb.isNull ? (ra.id - rb.id) : -1;
} else if (rb.IsNull) {
return 1;
}
return (ra.sort==rb.sort) ? (ra.id-rb.id) : (ra.sort<rb.sort ? -1 : 1);
}
......@@ -5,8 +5,9 @@
*/
package org.h2.store;
import java.util.BitSet;
import org.h2.engine.Session;
import org.h2.util.BitField;
/**
* The list of free pages of a page store. The format of a free list trunk page
......@@ -22,18 +23,17 @@ public class PageFreeList extends Page {
private static final int DATA_START = 3;
private final PageStore store;
private final BitField used;
private final BitSet used;
private final int pageCount;
private boolean full;
private Data data;
private PageFreeList(PageStore store, int pageId) {
private PageFreeList(PageStore store, int pageId, int pageCount, BitSet used) {
// kept in cache, and array list in page store
setPos(pageId);
this.store = store;
pageCount = (store.getPageSize() - DATA_START) * 8;
used = new BitField(pageCount);
used.set(0);
this.pageCount = pageCount;
this.used = used;
}
/**
......@@ -45,9 +45,15 @@ public class PageFreeList extends Page {
* @return the page
*/
static PageFreeList read(PageStore store, Data data, int pageId) {
PageFreeList p = new PageFreeList(store, pageId);
data.reset();
data.readByte();
data.readShortInt();
int length = store.getPageSize() - DATA_START;
byte[] b = new byte[length];
data.read(b, 0, b.length);
PageFreeList p = new PageFreeList(store, pageId, length * 8, BitSet.valueOf(b));
p.data = data;
p.read();
p.full = false;
return p;
}
......@@ -59,7 +65,10 @@ public class PageFreeList extends Page {
* @return the page
*/
static PageFreeList create(PageStore store, int pageId) {
return new PageFreeList(store, pageId);
int pageCount = (store.getPageSize() - DATA_START) * 8;
BitSet used = new BitSet(pageCount);
used.set(0);
return new PageFreeList(store, pageId, pageCount, used);
}
/**
......@@ -69,7 +78,7 @@ public class PageFreeList extends Page {
* @param first the first page to look for
* @return the page, or -1 if all pages are used
*/
int allocate(BitField exclude, int first) {
int allocate(BitSet exclude, int first) {
if (full) {
return -1;
}
......@@ -152,27 +161,17 @@ public class PageFreeList extends Page {
store.update(this);
}
/**
* Read the page from the disk.
*/
private void read() {
data.reset();
data.readByte();
data.readShortInt();
for (int i = 0; i < pageCount; i += 8) {
int x = data.readByte() & 255;
used.setByte(i, x);
}
full = false;
}
@Override
public void write() {
data = store.createData();
data.writeByte((byte) Page.TYPE_FREE_LIST);
data.writeShortInt(0);
for (int i = 0; i < pageCount; i += 8) {
data.writeByte((byte) used.getByte(i));
int cnt = pageCount >>> 3;
byte[] b = used.toByteArray();
int l = Math.min(b.length, cnt);
data.write(b, 0, l);
for (int i = cnt - l; i > 0; i--) {
data.writeByte((byte) 0);
}
store.writePage(getPos(), data);
}
......
......@@ -8,9 +8,10 @@ package org.h2.store;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.util.BitField;
/**
* An input stream that reads from a page store.
......@@ -132,8 +133,8 @@ public class PageInputStream extends InputStream {
*
* @return the bit set
*/
BitField allocateAllPages() {
BitField pages = new BitField();
BitSet allocateAllPages() {
BitSet pages = new BitSet();
int key = logKey;
PageStreamTrunk.Iterator it = new PageStreamTrunk.Iterator(
store, firstTrunkPage);
......
......@@ -8,6 +8,7 @@ package org.h2.store;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import org.h2.api.ErrorCode;
import org.h2.compress.CompressLZF;
......@@ -17,7 +18,6 @@ import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.result.Row;
import org.h2.result.RowFactory;
import org.h2.util.BitField;
import org.h2.util.IntArray;
import org.h2.util.IntIntHashMap;
import org.h2.util.New;
......@@ -132,13 +132,13 @@ public class PageLog {
* If the bit is set, the given page was written to the current log section.
* The undo entry of these pages doesn't need to be written again.
*/
private BitField undo = new BitField();
private BitSet undo = new BitSet();
/**
* The undo entry of those pages was written in any log section.
* These pages may not be used in the transaction log.
*/
private final BitField undoAll = new BitField();
private final BitSet undoAll = new BitSet();
/**
* The map of section ids (key) and data page where the section starts
......@@ -156,7 +156,7 @@ public class PageLog {
* The map of pages used by the transaction log.
* Only used during recovery.
*/
private BitField usedLogPages;
private BitSet usedLogPages;
/**
* This flag is set while freeing up pages.
......@@ -422,7 +422,7 @@ public class PageLog {
} catch (IOException e) {
trace.debug("log recovery completed");
}
undo = new BitField();
undo = new BitSet();
if (stage == RECOVERY_STAGE_REDO) {
usedLogPages = null;
}
......@@ -691,7 +691,7 @@ public class PageLog {
Data buffer = getBuffer();
buffer.writeByte((byte) CHECKPOINT);
write(buffer);
undo = new BitField();
undo = new BitSet();
logSectionId++;
logPos = 0;
pageOut.flush();
......
......@@ -5,9 +5,10 @@
*/
package org.h2.store;
import java.util.BitSet;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.util.BitField;
import org.h2.util.IntArray;
/**
......@@ -17,7 +18,7 @@ public class PageOutputStream {
private PageStore store;
private final Trace trace;
private final BitField exclude;
private final BitSet exclude;
private final boolean atEnd;
private final int minPageId;
......@@ -42,7 +43,7 @@ public class PageOutputStream {
* @param logKey the log key of the first trunk page
* @param atEnd whether only pages at the end of the file should be used
*/
public PageOutputStream(PageStore store, int trunkPage, BitField exclude,
public PageOutputStream(PageStore store, int trunkPage, BitSet exclude,
int logKey, boolean atEnd) {
this.trace = store.getTrace();
this.store = store;
......
......@@ -8,6 +8,7 @@ package org.h2.store;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
......@@ -42,7 +43,6 @@ import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.Table;
import org.h2.table.TableType;
import org.h2.util.BitField;
import org.h2.util.Cache;
import org.h2.util.CacheLRU;
import org.h2.util.CacheObject;
......@@ -180,7 +180,7 @@ public class PageStore implements CacheWriter {
/**
* Each free page is marked with a set bit.
*/
private final BitField freed = new BitField();
private final BitSet freed = new BitSet();
private final ArrayList<PageFreeList> freeLists = New.arrayList();
private boolean recordPageReads;
......@@ -1160,7 +1160,7 @@ public class PageStore implements CacheWriter {
* @param exclude the exclude list
* @param after all allocated pages are higher than this page
*/
void allocatePages(IntArray list, int pagesToAllocate, BitField exclude,
void allocatePages(IntArray list, int pagesToAllocate, BitSet exclude,
int after) {
list.ensureCapacity(list.size() + pagesToAllocate);
for (int i = 0; i < pagesToAllocate; i++) {
......@@ -1186,7 +1186,7 @@ public class PageStore implements CacheWriter {
return pos;
}
private int allocatePage(BitField exclude, int first) {
private int allocatePage(BitSet exclude, int first) {
int page;
for (int i = firstFreeListIndex;; i++) {
PageFreeList list = getFreeList(i);
......@@ -2020,8 +2020,8 @@ public class PageStore implements CacheWriter {
this.lockFile = lockFile;
}
public BitField getObjectIds() {
BitField f = new BitField();
public BitSet getObjectIds() {
BitSet f = new BitSet();
Cursor cursor = metaIndex.find(pageStoreSession, null, null);
while (cursor.next()) {
Row row = cursor.get();
......
......@@ -21,6 +21,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
......@@ -62,7 +63,6 @@ import org.h2.store.PageFreeList;
import org.h2.store.PageLog;
import org.h2.store.PageStore;
import org.h2.store.fs.FileUtils;
import org.h2.util.BitField;
import org.h2.util.IOUtils;
import org.h2.util.IntArray;
import org.h2.util.MathUtils;
......@@ -1248,15 +1248,10 @@ public class Recover extends Tool implements DataHandler {
private int dumpPageFreeList(PrintWriter writer, Data s, long pageId,
long pageCount) {
int pagesAddressed = PageFreeList.getPagesAddressed(pageSize);
BitField used = new BitField();
for (int i = 0; i < pagesAddressed; i += 8) {
int x = s.readByte() & 255;
for (int j = 0; j < 8; j++) {
if ((x & (1 << j)) != 0) {
used.set(i + j);
}
}
}
int len = pagesAddressed >> 3;
byte[] b = new byte[len];
s.read(b, 0, len);
BitSet used = BitSet.valueOf(b);
int free = 0;
for (long i = 0, j = pageId; i < pagesAddressed && j < pageCount; i++, j++) {
if (i == 0 || j % 100 == 0) {
......
/*
* Copyright 2004-2018 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.util;
import java.util.Arrays;
/**
* A list of bits.
*/
public final class BitField {
private static final int ADDRESS_BITS = 6;
private static final int BITS = 64;
private static final int ADDRESS_MASK = BITS - 1;
private long[] data;
private int maxLength;
public BitField() {
this(64);
}
public BitField(int capacity) {
data = new long[capacity >>> 3];
}
/**
* Get the index of the next bit that is not set.
*
* @param fromIndex where to start searching
* @return the index of the next disabled bit
*/
public int nextClearBit(int fromIndex) {
int i = fromIndex >> ADDRESS_BITS;
int max = data.length;
for (; i < max; i++) {
if (data[i] == -1) {
continue;
}
int j = Math.max(fromIndex, i << ADDRESS_BITS);
for (int end = j + 64; j < end; j++) {
if (!get(j)) {
return j;
}
}
}
return max << ADDRESS_BITS;
}
/**
* Get the bit at the given index.
*
* @param i the index
* @return true if the bit is enabled
*/
public boolean get(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return false;
}
return (data[addr] & getBitMask(i)) != 0;
}
/**
* Get the next 8 bits at the given index.
* The index must be a multiple of 8.
*
* @param i the index
* @return the next 8 bits
*/
public int getByte(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return 0;
}
return (int) (data[addr] >>> (i & (7 << 3)) & 255);
}
/**
* Combine the next 8 bits at the given index with OR.
* The index must be a multiple of 8.
*
* @param i the index
* @param x the next 8 bits (0 - 255)
*/
public void setByte(int i, int x) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= ((long) x) << (i & (7 << 3));
if (maxLength < i && x != 0) {
maxLength = i + 7;
}
}
/**
* Set bit at the given index to 'true'.
*
* @param i the index
*/
public void set(int i) {
int addr = i >> ADDRESS_BITS;
checkCapacity(addr);
data[addr] |= getBitMask(i);
if (maxLength < i) {
maxLength = i;
}
}
/**
* Set bit at the given index to 'false'.
*
* @param i the index
*/
public void clear(int i) {
int addr = i >> ADDRESS_BITS;
if (addr >= data.length) {
return;
}
data[addr] &= ~getBitMask(i);
}
private static long getBitMask(int i) {
return 1L << (i & ADDRESS_MASK);
}
private void checkCapacity(int size) {
if (size >= data.length) {
expandCapacity(size);
}
}
private void expandCapacity(int size) {
while (size >= data.length) {
int newSize = data.length == 0 ? 1 : data.length * 2;
data = Arrays.copyOf(data, newSize);
}
}
/**
* Enable or disable a number of bits.
*
* @param fromIndex the index of the first bit to enable or disable
* @param toIndex one plus the index of the last bit to enable or disable
* @param value the new value
*/
public void set(int fromIndex, int toIndex, boolean value) {
// go backwards so that OutOfMemory happens
// before some bytes are modified
for (int i = toIndex - 1; i >= fromIndex; i--) {
set(i, value);
}
if (value) {
if (toIndex > maxLength) {
maxLength = toIndex;
}
} else {
if (toIndex >= maxLength) {
maxLength = fromIndex;
}
}
}
private void set(int i, boolean value) {
if (value) {
set(i);
} else {
clear(i);
}
}
/**
* Get the index of the highest set bit plus one, or 0 if no bits are set.
*
* @return the length of the bit field
*/
public int length() {
int m = maxLength >> ADDRESS_BITS;
while (m > 0 && data[m] == 0) {
m--;
}
maxLength = (m << ADDRESS_BITS) +
(64 - Long.numberOfLeadingZeros(data[m]));
return maxLength;
}
}
......@@ -173,7 +173,6 @@ import org.h2.test.synth.thread.TestMulti;
import org.h2.test.unit.TestAnsCompression;
import org.h2.test.unit.TestAutoReconnect;
import org.h2.test.unit.TestBinaryArithmeticStream;
import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestBitStream;
import org.h2.test.unit.TestBnf;
import org.h2.test.unit.TestCache;
......@@ -903,7 +902,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestAnsCompression());
addTest(new TestAutoReconnect());
addTest(new TestBinaryArithmeticStream());
addTest(new TestBitField());
addTest(new TestBitStream());
addTest(new TestBnf());
addTest(new TestCache());
......
......@@ -63,8 +63,31 @@ public class TestCompatibility extends TestBase {
stat.execute("create schema s2");
stat.execute("create table s2.test(id int primary key, name varchar(255))");
stat.execute("insert into s2.test(id, name) values(1, 'a')");
stat.execute("insert into s2.test(id, name) values(1, 'b') " +
"on duplicate key update name = values(name)");
assertEquals(2, stat.executeUpdate("insert into s2.test(id, name) values(1, 'b') " +
"on duplicate key update name = values(name)"));
assertEquals(0, stat.executeUpdate("insert into s2.test(id, name) values(1, 'b') " +
"on duplicate key update name = values(name)"));
assertEquals(1, stat.executeUpdate("insert into s2.test(id, name) values(2, 'c') " +
"on duplicate key update name = values(name)"));
ResultSet rs = stat.executeQuery("select id, name from s2.test order by id");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertEquals("b", rs.getString(2));
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertEquals("c", rs.getString(2));
assertFalse(rs.next());
// Check qualified names in ON UPDATE case
assertEquals(2, stat.executeUpdate("insert into s2.test(id, name) values(2, 'd') " +
"on duplicate key update test.name = values(name)"));
assertThrows(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, stat)
.executeUpdate("insert into s2.test(id, name) values(2, 'd') " +
"on duplicate key update test2.name = values(name)");
assertEquals(2, stat.executeUpdate("insert into s2.test(id, name) values(2, 'e') " +
"on duplicate key update s2.test.name = values(name)"));
assertThrows(ErrorCode.SCHEMA_NAME_MUST_MATCH, stat)
.executeUpdate("insert into s2.test(id, name) values(2, 'd') " +
"on duplicate key update s3.test.name = values(name)");
stat.execute("drop schema s2 cascade");
c.close();
}
......
......@@ -49,6 +49,7 @@ public class TestMetaData extends TestBase {
testColumnMetaData();
testColumnPrecision();
testColumnDefault();
testColumnGenerated();
testCrossReferences();
testProcedureColumns();
testUDTs();
......@@ -234,6 +235,24 @@ public class TestMetaData extends TestBase {
conn.close();
}
private void testColumnGenerated() throws SQLException {
Connection conn = getConnection("metaData");
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs;
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(A INT, B INT AS A + 1)");
rs = meta.getColumns(null, null, "TEST", null);
rs.next();
assertEquals("A", rs.getString("COLUMN_NAME"));
assertEquals("NO", rs.getString("IS_GENERATEDCOLUMN"));
rs.next();
assertEquals("B", rs.getString("COLUMN_NAME"));
assertEquals("YES", rs.getString("IS_GENERATEDCOLUMN"));
assertFalse(rs.next());
stat.execute("DROP TABLE TEST");
conn.close();
}
private void testProcedureColumns() throws SQLException {
Connection conn = getConnection("metaData");
DatabaseMetaData meta = conn.getMetaData();
......@@ -404,7 +423,7 @@ public class TestMetaData extends TestBase {
meta.getDriverMinorVersion());
int majorVersion = 4;
assertEquals(majorVersion, meta.getJDBCMajorVersion());
assertEquals(0, meta.getJDBCMinorVersion());
assertEquals(1, meta.getJDBCMinorVersion());
assertEquals("H2", meta.getDatabaseProductName());
assertEquals(Connection.TRANSACTION_READ_COMMITTED,
meta.getDefaultTransactionIsolation());
......@@ -711,7 +730,7 @@ public class TestMetaData extends TestBase {
"SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH",
"ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATALOG",
"SCOPE_SCHEMA", "SCOPE_TABLE", "SOURCE_DATA_TYPE",
"IS_AUTOINCREMENT", "SCOPE_CATLOG" }, new int[] {
"IS_AUTOINCREMENT", "IS_GENERATEDCOLUMN" }, new int[] {
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER,
Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR,
......
/*
* Copyright 2004-2018 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.unit;
import java.util.BitSet;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.util.BitField;
/**
* A unit test for bit fields.
*/
public class TestBitField 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() {
testNextClearBit();
testByteOperations();
testRandom();
testGetSet();
testRandomSetRange();
}
private void testNextClearBit() {
BitSet set = new BitSet();
BitField field = new BitField();
set.set(0, 640);
field.set(0, 640, true);
assertEquals(set.nextClearBit(0), field.nextClearBit(0));
Random random = new Random(1);
field = new BitField();
field.set(0, 500, true);
for (int i = 0; i < 100000; i++) {
int a = random.nextInt(120);
int b = a + 1 + random.nextInt(200);
field.clear(a);
field.clear(b);
assertEquals(b, field.nextClearBit(a + 1));
field.set(a);
field.set(b);
}
}
private void testByteOperations() {
BitField used = new BitField();
testSetFast(used, false);
testSetFast(used, true);
}
private void testSetFast(BitField used, boolean init) {
int len = 10000;
Random random = new Random(1);
for (int i = 0, x = 0; i < len / 8; i++) {
int mask = random.nextInt() & 255;
if (init) {
assertEquals(mask, used.getByte(x));
x += 8;
// for (int j = 0; j < 8; j++, x++) {
// if (used.get(x) != ((mask & (1 << j)) != 0)) {
// throw Message.getInternalError(
// "Redo failure, block: " + x +
// " expected in-use bit: " + used.get(x));
// }
// }
} else {
used.setByte(x, mask);
x += 8;
// for (int j = 0; j < 8; j++, x++) {
// if ((mask & (1 << j)) != 0) {
// used.set(x);
// }
// }
}
}
}
private void testRandom() {
BitField bits = new BitField();
BitSet set = new BitSet();
int max = 300;
int count = 100000;
Random random = new Random(1);
for (int i = 0; i < count; i++) {
int idx = random.nextInt(max);
if (random.nextBoolean()) {
if (random.nextBoolean()) {
bits.set(idx);
set.set(idx);
} else {
bits.clear(idx);
set.clear(idx);
}
} else {
assertEquals(set.get(idx), bits.get(idx));
assertEquals(set.nextClearBit(idx), bits.nextClearBit(idx));
assertEquals(set.length(), bits.length());
}
}
}
private void testGetSet() {
BitField bits = new BitField();
for (int i = 0; i < 10000; i++) {
bits.set(i);
if (!bits.get(i)) {
fail("not set: " + i);
}
if (bits.get(i + 1)) {
fail("set: " + i);
}
}
for (int i = 0; i < 10000; i++) {
if (!bits.get(i)) {
fail("not set: " + i);
}
}
for (int i = 0; i < 1000; i++) {
int k = bits.nextClearBit(0);
if (k != 10000) {
fail("" + k);
}
}
}
private void testRandomSetRange() {
BitField bits = new BitField();
BitSet set = new BitSet();
Random random = new Random(1);
int maxOffset = 500;
int maxLen = 500;
int total = maxOffset + maxLen;
int count = 10000;
for (int i = 0; i < count; i++) {
int offset = random.nextInt(maxOffset);
int len = random.nextInt(maxLen);
boolean val = random.nextBoolean();
set.set(offset, offset + len, val);
bits.set(offset, offset + len, val);
for (int j = 0; j < total; j++) {
assertEquals(set.get(j), bits.get(j));
}
}
}
}
......@@ -771,4 +771,4 @@ openoffice organize libre systemtables gmane sea borders announced millennium al
opti excessively
iterators tech enums incompatibilities loses reimplement readme reorganize milli subdirectory linkplain inspections
geometries sourceschema destschema
geometries sourceschema destschema generatedcolumn alphanumerically usages
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论