提交 6d02b26f authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 9c01059b
#Fri Jan 18 08:04:40 CET 2008
#Mon Jan 28 07:19:50 CET 2008
javac=javac
benchmark.drivers.dir=C\:/data/java
path.servlet.jar=C\:/data/classpath/servlet-api.jar
......
......@@ -224,7 +224,7 @@
</target>
<target name="jarDb" depends="compileResources, manifest">
<javac executable="${javac}" srcdir="src/main" destdir="bin" debug="true">
<javac executable="${javac}" srcdir="src/main" destdir="bin" debug="false">
<include name="org/h2/*" />
<include name="org/h2/engine/**" />
<include name="org/h2/jdbc/**" />
......
......@@ -135,7 +135,6 @@ public abstract class Command implements CommandInterface {
cancel = false;
throw Message.getSQLException(ErrorCode.STATEMENT_WAS_CANCELLED);
}
session.throttle();
}
private void stop() throws SQLException {
......
......@@ -233,11 +233,10 @@ public abstract class Prepared {
* @throws SQLException if it was cancelled
*/
public void checkCancelled() throws SQLException {
// TODO strange code: probably checkCancelled should always be called on the session. fix & test after release 1.0
if (command != null) {
command.checkCancelled();
} else {
session.checkCancelled();
session.checkCancelled();
Command c = command != null ? command : session.getCurrentCommand();
if (c != null) {
c.checkCancelled();
}
}
......
......@@ -74,7 +74,8 @@ public class Session implements SessionInterface {
private boolean undoLogEnabled = true;
private boolean autoCommitAtTransactionEnd;
private String currentTransactionName;
private boolean isClosed;
private volatile long cancelAt;
private boolean closed;
private boolean rollbackMode;
private long sessionStart = System.currentTimeMillis();
private long currentCommandStart;
......@@ -150,7 +151,7 @@ public class Session implements SessionInterface {
if (!SysProperties.runFinalize) {
return;
}
if (!isClosed) {
if (!closed) {
throw Message.getInternalError("not closed", stackTrace);
}
}
......@@ -205,7 +206,7 @@ public class Session implements SessionInterface {
}
public Command prepareLocal(String sql) throws SQLException {
if (isClosed) {
if (closed) {
throw Message.getSQLException(ErrorCode.CONNECTION_BROKEN);
}
Parser parser = new Parser(this);
......@@ -320,13 +321,17 @@ public class Session implements SessionInterface {
return id;
}
public void cancel() {
cancelAt = System.currentTimeMillis();
}
public void close() throws SQLException {
if (!isClosed) {
if (!closed) {
try {
cleanTempTables(true);
database.removeSession(this);
} finally {
isClosed = true;
closed = true;
}
}
}
......@@ -420,7 +425,7 @@ public class Session implements SessionInterface {
if (traceModuleName == null) {
traceModuleName = Trace.JDBC + "[" + id + "]";
}
if (isClosed) {
if (closed) {
return new TraceSystem(null, false).getTrace(traceModuleName);
}
return database.getTrace(traceModuleName);
......@@ -512,7 +517,7 @@ public class Session implements SessionInterface {
}
public boolean isClosed() {
return isClosed;
return closed;
}
public void setThrottle(int throttle) {
......@@ -541,8 +546,14 @@ public class Session implements SessionInterface {
}
public void checkCancelled() throws SQLException {
if (currentCommand != null) {
currentCommand.checkCancelled();
throttle();
if (cancelAt == 0) {
return;
}
long time = System.currentTimeMillis();
if (time >= cancelAt) {
cancelAt = 0;
throw Message.getSQLException(ErrorCode.STATEMENT_WAS_CANCELLED);
}
}
......
......@@ -73,4 +73,9 @@ public interface SessionInterface {
* @return the data handler
*/
DataHandler getDataHandler();
/**
* Cancel the current or next command (called when closing a connection).
*/
void cancel();
}
......@@ -388,4 +388,8 @@ public class SessionRemote implements SessionInterface, DataHandler {
return lobSyncObject;
}
public void cancel() {
// TODO open another remote connection and cancel this session using a unique id (like PostgreSQL)
}
}
......@@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.log.UndoLogRecord;
......@@ -21,7 +22,6 @@ import org.h2.table.IndexColumn;
import org.h2.table.TableData;
import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueLob;
......@@ -35,7 +35,6 @@ public class ScanIndex extends BaseIndex {
private ObjectArray rows = new ObjectArray();
private Storage storage;
private TableData tableData;
private boolean containsLargeObject;
private int rowCountDiff;
private HashMap sessionRowCount;
private HashSet delta;
......@@ -54,11 +53,6 @@ public class ScanIndex extends BaseIndex {
rowCount = count;
table.setRowCount(count);
trace.info("open existing " + table.getName() + " rows: " + count);
for (int i = 0; i < columns.length; i++) {
if (DataType.isLargeObject(columns[i].column.getType())) {
containsLargeObject = true;
}
}
}
public void remove(Session session) throws SQLException {
......@@ -75,7 +69,7 @@ public class ScanIndex extends BaseIndex {
} else {
storage.truncate(session);
}
if (containsLargeObject && tableData.isPersistent()) {
if (tableData.getContainsLargeObject() && tableData.isPersistent()) {
ValueLob.removeAllForTable(database, table.getId());
}
tableData.setRowCount(0);
......@@ -104,7 +98,7 @@ public class ScanIndex extends BaseIndex {
public void add(Session session, Row row) throws SQLException {
if (storage != null) {
if (containsLargeObject) {
if (tableData.getContainsLargeObject()) {
for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i);
Value v2 = v.link(database, getId());
......@@ -164,7 +158,7 @@ public class ScanIndex extends BaseIndex {
public void remove(Session session, Row row) throws SQLException {
if (storage != null) {
storage.removeRecord(session, row.getPos());
if (containsLargeObject) {
if (tableData.getContainsLargeObject()) {
for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i);
if (v.isLinked()) {
......
......@@ -234,6 +234,7 @@ public class JdbcConnection extends TraceObject implements Connection {
if (session == null) {
return;
}
session.cancel();
synchronized (session) {
try {
if (!session.isClosed()) {
......
......@@ -15,6 +15,7 @@ import org.h2.value.Value;
* Represents a row in a table.
*/
public class Row extends Record implements SearchRow {
public static final int MEMORY_CALCULATE = -1;
private final Value[] data;
private final int memory;
......@@ -63,7 +64,14 @@ public class Row extends Record implements SearchRow {
}
public int getMemorySize() {
return blockCount * (DiskFile.BLOCK_SIZE / 16) + memory * 4;
if (memory != MEMORY_CALCULATE) {
return blockCount * (DiskFile.BLOCK_SIZE / 16) + memory * 4;
}
int m = blockCount * (DiskFile.BLOCK_SIZE / 16);
for (int i = 0; data != null && i < data.length; i++) {
m += data[i].getMemory();
}
return m;
}
public String toString() {
......
......@@ -34,6 +34,7 @@ import org.h2.store.RecordReader;
import org.h2.util.MathUtils;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
/**
......@@ -42,6 +43,7 @@ import org.h2.value.Value;
* instead it is kept in the indexes. There is at least one index, the scan index.
*/
public class TableData extends Table implements RecordReader {
private final boolean clustered;
private ScanIndex scanIndex;
private long rowCount;
private Session lockExclusive;
......@@ -50,7 +52,7 @@ public class TableData extends Table implements RecordReader {
private boolean globalTemporary;
private final ObjectArray indexes = new ObjectArray();
private long lastModificationId;
private final boolean clustered;
private boolean containsLargeObject;
public TableData(Schema schema, String tableName, int id, ObjectArray columns,
boolean persistent, boolean clustered) throws SQLException {
......@@ -63,6 +65,11 @@ public class TableData extends Table implements RecordReader {
scanIndex = new ScanIndex(this, id, IndexColumn.wrap(cols), IndexType.createScan(persistent));
indexes.add(scanIndex);
}
for (int i = 0; i < cols.length; i++) {
if (DataType.isLargeObject(cols[i].getType())) {
containsLargeObject = true;
}
}
traceLock = database.getTrace(Trace.LOCK);
}
......@@ -457,7 +464,9 @@ public class TableData extends Table implements RecordReader {
for (int i = 0; i < len; i++) {
data[i] = s.readValue();
}
return new Row(data, memoryPerRow);
int memory = containsLargeObject ? Row.MEMORY_CALCULATE : memoryPerRow;
Row row = new Row(data, memory);
return row;
}
public void setRowCount(int count) {
......@@ -530,4 +539,8 @@ public class TableData extends Table implements RecordReader {
return clustered;
}
public boolean getContainsLargeObject() {
return containsLargeObject;
}
}
......@@ -357,7 +357,7 @@ public class TableLink extends Table {
boolean deleteInsert;
if (emitUpdates) {
for (rows.reset(); rows.hasNext();) {
session.checkCancelled();
prepared.checkCancelled();
Row oldRow = rows.next();
Row newRow = rows.next();
linkedIndex.update(session, oldRow, newRow);
......
......@@ -13,6 +13,11 @@ public class MemoryUtils {
private static final int GC_DELAY = 50;
private static final int MAX_GC = 8;
/**
* Get the used memory in KB.
*
* @return the used memory
*/
public static int getMemoryUsed() {
collectGarbage();
Runtime rt = Runtime.getRuntime();
......@@ -20,6 +25,11 @@ public class MemoryUtils {
return (int) (mem >> 10);
}
/**
* Get the free memory in KB.
*
* @return the used memory
*/
public static int getMemoryFree() {
collectGarbage();
Runtime rt = Runtime.getRuntime();
......
......@@ -42,15 +42,15 @@ public class TempFileDeleter {
} catch (Exception e) {
// TODO log such errors?
}
deleteUnused();
}
deleteUnused();
}
public static void deleteUnused() {
// Mystery: I don't know how QUEUE could get null, but two independent
// people reported NullPointerException here - if somebody understands
// how it could happen please report it!
// Setup: webapp under Tomcat, exception occurs during undeploy
// Environment: web application under Tomcat, exception occurs during undeploy
while (QUEUE != null) {
Reference ref = QUEUE.poll();
if (ref == null) {
......
......@@ -116,103 +116,103 @@ public class DataType {
add(Value.SHORT, Types.SMALLINT, "Short",
createDecimal(ValueShort.PRECISION, ValueShort.PRECISION, 0, ValueShort.DISPLAY_SIZE, false, false),
new String[]{"SMALLINT", "YEAR", "INT2"},
1
5
);
add(Value.INT, Types.INTEGER, "Int",
createDecimal(ValueInt.PRECISION, ValueInt.PRECISION, 0, ValueInt.DISPLAY_SIZE, false, false),
new String[]{"INTEGER", "INT", "MEDIUMINT", "INT4", "SIGNED"},
1
5
);
add(Value.LONG, Types.BIGINT, "Long",
createDecimal(ValueLong.PRECISION, ValueLong.PRECISION, 0, ValueLong.DISPLAY_SIZE, false, false),
new String[]{"BIGINT", "INT8"},
1
5
);
add(Value.LONG, Types.BIGINT, "Long",
createDecimal(ValueLong.PRECISION, ValueLong.PRECISION, 0, ValueLong.DISPLAY_SIZE, false, true),
new String[]{"IDENTITY", "SERIAL"},
1
5
);
add(Value.DECIMAL, Types.DECIMAL, "BigDecimal",
createDecimal(Integer.MAX_VALUE, ValueDecimal.DEFAULT_PRECISION, ValueDecimal.DEFAULT_SCALE, ValueDecimal.DEFAULT_DISPLAY_SIZE, true, false),
new String[]{"DECIMAL", "DEC"},
7
17
// TODO value: are NaN, Inf, -Inf,... supported as well?
);
add(Value.DECIMAL, Types.NUMERIC, "BigDecimal",
createDecimal(Integer.MAX_VALUE, ValueDecimal.DEFAULT_PRECISION, ValueDecimal.DEFAULT_SCALE, ValueDecimal.DEFAULT_DISPLAY_SIZE, true, false),
new String[]{"NUMERIC", "NUMBER"},
7
17
// TODO value: are NaN, Inf, -Inf,... supported as well?
);
add(Value.FLOAT, Types.REAL, "Float",
createDecimal(ValueFloat.PRECISION, ValueFloat.PRECISION, 0, ValueFloat.DISPLAY_SIZE, false, false),
new String[] {"REAL", "FLOAT4"},
1
5
);
add(Value.DOUBLE, Types.DOUBLE, "Double",
createDecimal(ValueDouble.PRECISION, ValueDouble.PRECISION, 0, ValueDouble.DISPLAY_SIZE, false, false),
new String[] { "DOUBLE", "DOUBLE PRECISION" },
1
4
);
add(Value.DOUBLE, Types.FLOAT, "Double",
createDecimal(ValueDouble.PRECISION, ValueDouble.PRECISION, 0, ValueDouble.DISPLAY_SIZE, false, false),
new String[] {"FLOAT", "FLOAT8" },
1
4
// TODO value: show min and max values, E format if supported
);
add(Value.TIME, Types.TIME, "Time",
createDate(ValueTime.PRECISION, "TIME", 0, ValueTime.DISPLAY_SIZE),
new String[]{"TIME"},
4
10
// TODO value: min / max for time
);
add(Value.DATE, Types.DATE, "Date",
createDate(ValueDate.PRECISION, "DATE", 0, ValueDate.DISPLAY_SIZE),
new String[]{"DATE"},
4
10
// TODO value: min / max for date
);
add(Value.TIMESTAMP, Types.TIMESTAMP, "Timestamp",
createDate(ValueTimestamp.PRECISION, "TIMESTAMP", ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.DISPLAY_SIZE),
new String[]{"TIMESTAMP", "DATETIME", "SMALLDATETIME"},
4
12
// TODO value: min / max for timestamp
);
add(Value.BYTES, Types.VARBINARY, "Bytes",
createString(false),
new String[]{"VARBINARY"},
4
8
);
add(Value.BYTES, Types.BINARY, "Bytes",
createString(false),
new String[]{"BINARY", "RAW", "BYTEA", "LONG RAW"},
4
8
);
add(Value.BYTES, Types.LONGVARBINARY, "Bytes",
createString(false),
new String[]{"LONGVARBINARY"},
4
8
);
add(Value.UUID, Types.BINARY, "Bytes",
createString(false),
new String[]{"UUID"},
4
8
);
add(Value.JAVA_OBJECT, Types.OTHER, "Object",
createString(false),
new String[]{"OTHER", "OBJECT", "JAVA_OBJECT"},
4
8
);
add(Value.BLOB, Types.BLOB, "Bytes",
createString(false),
new String[]{"BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "IMAGE", "OID"},
4
8
);
add(Value.CLOB, Types.CLOB, "String",
createString(true),
new String[]{"CLOB", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "NTEXT", "NCLOB"},
4
10
);
DataType dataType = new DataType();
dataType.prefix = "(";
......@@ -220,13 +220,13 @@ public class DataType {
add(Value.ARRAY, Types.ARRAY, "Array",
dataType,
new String[]{"ARRAY"},
2
10
);
dataType = new DataType();
add(Value.RESULT_SET, 0, "ResultSet",
dataType,
new String[]{"RESULT_SET"},
2
20
);
for (int i = 0; i < typesByValueType.length; i++) {
DataType dt = typesByValueType[i];
......
......@@ -76,6 +76,15 @@ public abstract class Value {
*/
public abstract int getDisplaySize();
/**
* Get the memory used by this object.
*
* @return the memory used in bytes
*/
public int getMemory() {
return DataType.getDataType(getType()).memory * 4;
}
/**
* Get the value as a string.
*
......
......@@ -133,4 +133,12 @@ public class ValueArray extends Value {
return true;
}
public int getMemory() {
int memory = 0;
for (int i = 0; i < values.length; i++) {
memory += values[i].getMemory();
}
return memory;
}
}
......@@ -70,4 +70,8 @@ abstract class ValueBytesBase extends Value {
return v instanceof ValueBytesBase && ByteUtils.compareNotNull(value, ((ValueBytesBase) v).value) == 0;
}
public int getMemory() {
return value.length + 4;
}
}
......@@ -185,4 +185,8 @@ public class ValueDecimal extends Value {
return v instanceof ValueDecimal && value.equals(((ValueDecimal) v).value);
}
public int getMemory() {
return getString().length() * 3 + 120;
}
}
......@@ -642,4 +642,11 @@ public class ValueLob extends Value {
this.fileName = fileName;
}
public int getMemory() {
if (small != null) {
return small.length + 32;
}
return 128;
}
}
......@@ -60,4 +60,8 @@ abstract class ValueStringBase extends Value {
return v instanceof ValueString && value.equals(((ValueString) v).value);
}
public int getMemory() {
return value.length() * 2 + 30;
}
}
......@@ -104,6 +104,7 @@ import org.h2.test.unit.TestStringUtils;
import org.h2.test.unit.TestTools;
import org.h2.test.unit.TestValue;
import org.h2.test.unit.TestValueHashMap;
import org.h2.test.unit.TestValueMemory;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
......@@ -121,12 +122,12 @@ Random test:
cd bin
del *.db
start cmd /k "java -cp .;%H2DRIVERS% org.h2.test.TestAll join >testJoin.txt"
start cmd /k "java -cp . org.h2.test.TestAll crash >testCrash.txt"
start cmd /k "java -cp . org.h2.test.TestAll synth >testSynth.txt"
start cmd /k "java -cp . org.h2.test.TestAll all >testAll.txt"
start cmd /k "java -cp . org.h2.test.TestAll random >testRandom.txt"
start cmd /k "java -cp . org.h2.test.TestAll btree >testBtree.txt"
start cmd /k "java -cp . org.h2.test.TestAll halt >testHalt.txt"
java -cp . org.h2.test.TestAll crash >testCrash.txt
java org.h2.test.TestAll timer
......@@ -150,6 +151,51 @@ java org.h2.test.TestAll timer
/*
adjust cache memory usage
simple pure java config file (interpreted)
DROP ALL OBJECTS;
SET MAX_LENGTH_INPLACE_LOB 32768;
CREATE TABLE TEST(ID IDENTITY, DATA CLOB);
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
@LOOP 1000 INSERT INTO TEST(DATA) VALUES(SPACE(32000));
CALL MEMORY_USED();
ResultRemote.close()
public void close() {
result = null;
// NULL OUT THE SESSION REFERENCE
sendClose();
if (lobValues != null) {
for (int i = 0; i < lobValues.size(); i++) {
Value v = (Value) lobValues.get(i);
try {
v.close();
} catch (SQLException e) {
// BANG NullPointerException
session.getTrace().error("delete lob " + v.getSQL(), e);
}
}
lobValues = null;
}
}
orphan?
javadoc: design patterns
......@@ -166,6 +212,8 @@ Roadmap:
Move Maven 2 repository from hsql.sf.net to h2database.sf.net
History:
The cache size was not correctly calculated for tables with large objects (specially if compression is used).
This could lead to out-of-memory exceptions.
The exception "Hexadecimal string contains non-hex character" was not always thrown when it should have been. Fixed.
The H2 Console now provides a link to the documentation when an error occurs (H2 databases only so far).
......@@ -592,6 +640,7 @@ Features of H2
new TestTools().runTest(this);
new TestValue().runTest(this);
new TestValueHashMap().runTest(this);
new TestValueMemory().runTest(this);
afterTest();
}
......
......@@ -183,7 +183,7 @@ public class TestCases extends TestBase {
}
});
t.start();
Thread.sleep(500);
Thread.sleep(300);
long time = System.currentTimeMillis();
conn.close();
t.join(5000);
......
......@@ -49,12 +49,12 @@ public class TestExclusive extends TestBase {
t.start();
state[0] = 1;
stat.execute("set exclusive false");
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
if (state[0] == 2) {
break;
}
}
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
if (state[0] == 2) {
break;
}
}
check(state[0], 2);
stat.execute("set exclusive true");
conn.close();
......
......@@ -79,7 +79,7 @@ public class TestMemoryUsage extends TestBase {
// update
time = System.currentTimeMillis();
prep = conn.prepareStatement("UPDATE TEST SET NAME='Hallo Welt' WHERE ID = ?");
prep = conn.prepareStatement("UPDATE TEST SET NAME='Hallo Welt' || ID WHERE ID = ?");
for (int i = 0; i < len; i++) {
prep.setInt(1, i);
prep.execute();
......
......@@ -103,12 +103,12 @@ public class TestSessionsLocks extends TestBase {
rs = stat.executeQuery("CALL CANCEL_SESSION(" + otherId + ")");
rs.next();
if (rs.getBoolean(1)) {
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
if (done[0]) {
break;
}
}
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
if (done[0]) {
break;
}
}
check(done[0]);
break;
} else {
......
package org.h2.test.unit;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Random;
import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.test.TestBase;
import org.h2.util.MemoryUtils;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueByte;
import org.h2.value.ValueBytes;
import org.h2.value.ValueDate;
import org.h2.value.ValueDecimal;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueJavaObject;
import org.h2.value.ValueLob;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueStringFixed;
import org.h2.value.ValueStringIgnoreCase;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
public class TestValueMemory extends TestBase implements DataHandler {
private Random random = new Random(1);
public void test() throws Exception {
for (int i = 0; i < Value.TYPE_COUNT; i++) {
testType(i);
}
}
private void testType(int type) throws SQLException {
System.gc();
System.gc();
long first = MemoryUtils.getMemoryUsed();
ArrayList list = new ArrayList();
long memory = 0;
for (int i = 0; memory < 1000000; i++) {
Value v = create(type);
memory += v.getMemory();
list.add(v);
}
Object[] array = list.toArray();
list = null;
System.gc();
System.gc();
long used = MemoryUtils.getMemoryUsed() - first;
memory /= 1024;
System.out.println("Type: " + type + " Used memory: " + used + " calculated: " + memory + " " + array.length);
if (Math.abs(used - memory) > used / 10) {
int todoMaybeThrowError;
System.out.println("ERROR");
}
}
Value create(int type) throws SQLException {
switch (type) {
case Value.NULL:
return ValueNull.INSTANCE;
case Value.BOOLEAN:
return ValueBoolean.get(false);
case Value.BYTE:
return ValueByte.get((byte) random.nextInt());
case Value.SHORT:
return ValueShort.get((short) random.nextInt());
case Value.INT:
return ValueInt.get(random.nextInt());
case Value.LONG:
return ValueLong.get(random.nextLong());
case Value.DECIMAL:
return ValueDecimal.get(new BigDecimal(random.nextInt() /*+ "12123344563456345634565234523451312312" */));
case Value.DOUBLE:
return ValueDouble.get(random.nextDouble());
case Value.FLOAT:
return ValueFloat.get(random.nextFloat());
case Value.TIME:
return ValueTime.get(new java.sql.Time(random.nextLong()));
case Value.DATE:
return ValueDate.get(new java.sql.Date(random.nextLong()));
case Value.TIMESTAMP:
return ValueTimestamp.get(new java.sql.Timestamp(random.nextLong()));
case Value.BYTES:
return ValueBytes.get(randomBytes(random.nextInt(1000)));
case Value.STRING:
return ValueString.get(randomString(random.nextInt(100)));
case Value.STRING_IGNORECASE:
return ValueStringIgnoreCase.get(randomString(random.nextInt(100)));
case Value.BLOB: {
int len = (int) Math.abs(random.nextGaussian() * 100);
byte[] data = randomBytes(len);
return ValueLob.createBlob(new ByteArrayInputStream(data), len, this);
}
case Value.CLOB: {
int len = (int) Math.abs(random.nextGaussian() * 100);
String s = randomString(len);
return ValueLob.createClob(new StringReader(s), len, this);
}
case Value.ARRAY: {
int len = random.nextInt(20);
Value[] list = new Value[len];
for (int i = 0; i < list.length; i++) {
list[i] = create(Value.STRING);
}
return ValueArray.get(list);
}
case Value.RESULT_SET:
// not supported currently
return ValueNull.INSTANCE;
case Value.JAVA_OBJECT:
return ValueJavaObject.getNoCopy(randomBytes(random.nextInt(100)));
case Value.UUID:
return ValueUuid.get(random.nextLong(), random.nextLong());
case Value.STRING_FIXED:
return ValueStringFixed.get(randomString(random.nextInt(100)));
default:
throw new Error("type=" + type);
}
}
byte[] randomBytes(int len) {
byte[] data = new byte[len];
if (random.nextBoolean()) {
// don't initialize always (compression)
random.nextBytes(data);
}
return data;
}
String randomString(int len) {
char[] chars = new char[len];
if (random.nextBoolean()) {
// don't initialize always (compression)
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) (random.nextGaussian() * 100);
}
}
return new String(chars);
}
public int allocateObjectId(boolean needFresh, boolean dataFile) {
return 0;
}
public void checkPowerOff() throws SQLException {
}
public void checkWritingAllowed() throws SQLException {
}
public int compareTypeSave(Value a, Value b) throws SQLException {
return 0;
}
public String createTempFile() throws SQLException {
return baseDir + "/valueMemory/data";
// try {
// return File.createTempFile("temp", ".tmp", new File(baseDir + "/valueMemory/data")).getAbsolutePath();
// } catch (IOException e) {
// throw new SQLException();
// }
}
public void freeUpDiskSpace() throws SQLException {
}
public int getChecksum(byte[] data, int start, int end) {
return 0;
}
public String getDatabasePath() {
return baseDir + "/valueMemory";
}
public String getLobCompressionAlgorithm(int type) {
return "LZF";
}
public Object getLobSyncObject() {
return this;
}
public int getMaxLengthInplaceLob() {
return 100;
}
public boolean getTextStorage() {
return false;
}
public void handleInvalidChecksum() throws SQLException {
}
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return FileStore.open(this, name, mode, null);
}
}
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* glassfish/bootstrap/legal/CDDLv1.0.txt or
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
* See the License for the specific language governing
*
* You can obtain a copy of the license at
* glassfish/bootstrap/legal/CDDLv1.0.txt or
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
* add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your
* own identifying information: Portions Copyright [yyyy]
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
* add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your
* own identifying information: Portions Copyright [yyyy]
* [name of copyright owner]
*/
// Copyright (c) 1998, 2006, Oracle. All rights reserved.
// Copyright (c) 1998, 2006, Oracle. All rights reserved.
package oracle.toplink.essentials.platform.database;
import java.util.*;
......@@ -33,7 +33,13 @@ import oracle.toplink.essentials.internal.databaseaccess.*;
import oracle.toplink.essentials.internal.sessions.AbstractSession;
/**
* <p><b>Purpose</b>: Provides H2 specific behaviour.
* This platform provides H2 specific behaviour.
* Use the following setting to enable this platform:
* <pre>
* &lt;property
* name="toplink.platform.class.name"
* value="oracle.toplink.essentials.platform.database.H2Platform"/>
* </pre>
*/
public class H2Platform extends DatabasePlatform {
public H2Platform() {
......@@ -58,18 +64,18 @@ public class H2Platform extends DatabasePlatform {
fieldTypeMapping.put(byte[].class, new FieldTypeDefinition("BINARY", false));
fieldTypeMapping.put(char[].class, new FieldTypeDefinition("LONGVARCHAR", false));
fieldTypeMapping.put(java.sql.Blob.class, new FieldTypeDefinition("BINARY", false));
fieldTypeMapping.put(java.sql.Clob.class, new FieldTypeDefinition("LONGVARCHAR", false));
fieldTypeMapping.put(java.sql.Clob.class, new FieldTypeDefinition("LONGVARCHAR", false));
fieldTypeMapping.put(java.sql.Date.class, new FieldTypeDefinition("DATE", false));
fieldTypeMapping.put(java.sql.Time.class, new FieldTypeDefinition("TIME", false));
fieldTypeMapping.put(java.sql.Timestamp.class, new FieldTypeDefinition("TIMESTAMP", false));
return fieldTypeMapping;
}
// public boolean isHSQL() {
// return true;
// }
// }
public boolean isH2() {
return true;
......@@ -78,16 +84,16 @@ public class H2Platform extends DatabasePlatform {
public boolean supportsForeignKeyConstraints() {
return true;
}
public ValueReadQuery buildSelectQueryForNativeSequence(String seqName, Integer size) {
return new ValueReadQuery("CALL NEXT VALUE FOR " + getQualifiedSequenceName(seqName));
// return new ValueReadQuery("SELECT " + getQualifiedSequenceName(seqName) + ".NEXTVAL FROM DUAL");
}
}
public boolean supportsNativeSequenceNumbers() {
return true;
}
protected String getQualifiedSequenceName(String seqName) {
if (getTableQualifier().equals("")) {
return seqName;
......@@ -95,22 +101,22 @@ public class H2Platform extends DatabasePlatform {
return getTableQualifier() + "." + seqName;
}
}
public boolean supportsSelectForUpdateNoWait() {
return true;
}
protected ExpressionOperator todayOperator() {
return ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.Today, "SYSDATE");
}
}
protected void initializePlatformOperators() {
super.initializePlatformOperators();
addOperator(ExpressionOperator.simpleMath(ExpressionOperator.Concat, "||"));
}
}
public boolean shouldUseJDBCOuterJoinSyntax() {
return false;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论