提交 1865ce3d authored 作者: Thomas Mueller's avatar Thomas Mueller

javadocs

上级 528531e5
...@@ -109,6 +109,16 @@ CREATE LINKED TABLE LINK('org.postgresql.Driver', 'jdbc:postgresql:test', 'sa', ...@@ -109,6 +109,16 @@ CREATE LINKED TABLE LINK('org.postgresql.Driver', 'jdbc:postgresql:test', 'sa',
</pre> </pre>
<p> <p>
It is then possible to access the table in the usual way. It is then possible to access the table in the usual way.
Whenever the linked table is accessed, the database issues specific queries over JDBC.
Using the example above, if you issue the query <code>SELECT * FROM LINK WHERE ID=1</code>,
then the following query is run against the PostgreSQL database: <code>SELECT * FROM TEST WHERE ID=?</code>.
The same happens for insert and update statements. Only simple statements are executed against the
target database, that means no joins. Prepared statements are used where possible.
</p>
<p>
To view the statements that are executed against the target table, set the trace level to 3.
</p>
<p>
There is a restriction when inserting data to this table: When inserting or updating rows into the table, There is a restriction when inserting data to this table: When inserting or updating rows into the table,
NULL and values that are not set in the insert statement are both inserted as NULL. NULL and values that are not set in the insert statement are both inserted as NULL.
This may not have the desired effect if a default value in the target table is other than NULL. This may not have the desired effect if a default value in the target table is other than NULL.
...@@ -122,6 +132,9 @@ Oracle XE needs to be restarted after changing these values: ...@@ -122,6 +132,9 @@ Oracle XE needs to be restarted after changing these values:
alter system set processes=100 scope=spfile; alter system set processes=100 scope=spfile;
alter system set sessions=100 scope=spfile; alter system set sessions=100 scope=spfile;
</pre> </pre>
<p>
</p>
<br /><a name="transaction_isolation"></a> <br /><a name="transaction_isolation"></a>
<h2>Transaction Isolation</h2> <h2>Transaction Isolation</h2>
......
...@@ -17,7 +17,8 @@ Change Log ...@@ -17,7 +17,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>RunScript tool: new options to show and check the results of queries. <li>Linked tables: To view the statements that are executed against the target table, set the trace level to 3.
</li><li>RunScript tool: new options to show and check the results of queries.
</li><li>Deadlocks are now detected. One transaction is rolled back automatically. </li><li>Deadlocks are now detected. One transaction is rolled back automatically.
</li><li>The Lucene fulltext index was always re-created when opening a </li><li>The Lucene fulltext index was always re-created when opening a
database with fulltext index enabled. database with fulltext index enabled.
......
...@@ -313,6 +313,7 @@ Roadmap ...@@ -313,6 +313,7 @@ Roadmap
</li><li>Convert SQL-injection-2.txt to html document, include SQLInjection.java sample </li><li>Convert SQL-injection-2.txt to html document, include SQLInjection.java sample
</li><li>Send SQL Injection solution proposal to MySQL, Derby, HSQLDB,... </li><li>Send SQL Injection solution proposal to MySQL, Derby, HSQLDB,...
</li><li>Improve LOB in directories performance </li><li>Improve LOB in directories performance
</li><li>Optimize OR conditions: convert them to IN(...) if possible.
</li><li>Web site design: http://www.igniterealtime.org/projects/openfire/index.jsp </li><li>Web site design: http://www.igniterealtime.org/projects/openfire/index.jsp
</li><li>HSQLDB compatibility: Openfire server uses: CREATE SCHEMA PUBLIC AUTHORIZATION DBA; </li><li>HSQLDB compatibility: Openfire server uses: CREATE SCHEMA PUBLIC AUTHORIZATION DBA;
CREATE USER SA PASSWORD ""; GRANT DBA TO SA; SET SCHEMA PUBLIC CREATE USER SA PASSWORD ""; GRANT DBA TO SA; SET SCHEMA PUBLIC
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -1035,7 +1035,7 @@ public class Database implements DataHandler { ...@@ -1035,7 +1035,7 @@ public class Database implements DataHandler {
// remove all session variables // remove all session variables
if (persistent) { if (persistent) {
try { try {
ValueLob.removeAllForTable(this, ValueLob.TABLE_ID_SESSION); ValueLob.removeAllForTable(this, ValueLob.TABLE_ID_SESSION_VARIABLE);
} catch (SQLException e) { } catch (SQLException e) {
traceSystem.getTrace(Trace.DATABASE).error("close", e); traceSystem.getTrace(Trace.DATABASE).error("close", e);
} }
......
...@@ -130,7 +130,7 @@ public class Session implements SessionInterface { ...@@ -130,7 +130,7 @@ public class Session implements SessionInterface {
} else { } else {
if (value instanceof ValueLob) { if (value instanceof ValueLob) {
// link it, to make sure we have our own file // link it, to make sure we have our own file
value = value.link(database, ValueLob.TABLE_ID_SESSION); value = value.link(database, ValueLob.TABLE_ID_SESSION_VARIABLE);
} }
old = (Value) variables.put(name, value); old = (Value) variables.put(name, value);
} }
......
...@@ -23,6 +23,7 @@ import org.h2.index.IndexType; ...@@ -23,6 +23,7 @@ import org.h2.index.IndexType;
import org.h2.index.LinkedIndex; import org.h2.index.LinkedIndex;
import org.h2.log.UndoLogRecord; import org.h2.log.UndoLogRecord;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.RowList; import org.h2.result.RowList;
import org.h2.schema.Schema; import org.h2.schema.Schema;
...@@ -307,6 +308,10 @@ public class TableLink extends Table { ...@@ -307,6 +308,10 @@ public class TableLink extends Table {
* @return the prepared statement * @return the prepared statement
*/ */
public PreparedStatement getPreparedStatement(String sql) throws SQLException { public PreparedStatement getPreparedStatement(String sql) throws SQLException {
Trace trace = database.getTrace(Trace.TABLE);
if (trace.isDebugEnabled()) {
trace.debug(getName() + ":\n" + sql);
}
if (conn == null) { if (conn == null) {
throw connectException; throw connectException;
} }
......
...@@ -16,6 +16,11 @@ public class BitField { ...@@ -16,6 +16,11 @@ public class BitField {
private static final int ADDRESS_MASK = BITS - 1; private static final int ADDRESS_MASK = BITS - 1;
private long[] data = new long[10]; private long[] data = new long[10];
/**
* Get the index of the last bit that is set.
*
* @return the index of the last enabled bit
*/
public int getLastSetBit() { public int getLastSetBit() {
int i = (data.length << ADDRESS_BITS) - 1; int i = (data.length << ADDRESS_BITS) - 1;
while (i >= 0) { while (i >= 0) {
...@@ -27,6 +32,12 @@ public class BitField { ...@@ -27,6 +32,12 @@ public class BitField {
return -1; return -1;
} }
/**
* Get the index of the next bit that is set.
*
* @param fromIndex where to start searching
* @return the index of the next enabled bit
*/
public int nextSetBit(int fromIndex) { public int nextSetBit(int fromIndex) {
int i = fromIndex >> ADDRESS_BITS; int i = fromIndex >> ADDRESS_BITS;
int max = data.length; int max = data.length;
...@@ -44,6 +55,12 @@ public class BitField { ...@@ -44,6 +55,12 @@ public class BitField {
return -1; return -1;
} }
/**
* 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) { public int nextClearBit(int fromIndex) {
int i = fromIndex >> ADDRESS_BITS; int i = fromIndex >> ADDRESS_BITS;
int max = data.length; int max = data.length;
...@@ -60,6 +77,12 @@ public class BitField { ...@@ -60,6 +77,12 @@ public class BitField {
return fromIndex; return fromIndex;
} }
/**
* Get the bit mask of the bits at the given index.
*
* @param i the index (must be a multiple of 64)
* @return the bit mask as a long
*/
public long getLong(int i) { public long getLong(int i) {
int addr = getAddress(i); int addr = getAddress(i);
if (addr >= data.length) { if (addr >= data.length) {
...@@ -68,6 +91,12 @@ public class BitField { ...@@ -68,6 +91,12 @@ public class BitField {
return data[addr]; return data[addr];
} }
/**
* Get the bit at the given index.
*
* @param i the index
* @return true if the bit is enabled
*/
public boolean get(int i) { public boolean get(int i) {
int addr = getAddress(i); int addr = getAddress(i);
if (addr >= data.length) { if (addr >= data.length) {
...@@ -76,12 +105,22 @@ public class BitField { ...@@ -76,12 +105,22 @@ public class BitField {
return (data[addr] & getBitMask(i)) != 0; return (data[addr] & getBitMask(i)) != 0;
} }
/**
* Set bit at the given index to 'true'.
*
* @param i the index
*/
public void set(int i) { public void set(int i) {
int addr = getAddress(i); int addr = getAddress(i);
checkCapacity(addr); checkCapacity(addr);
data[addr] |= getBitMask(i); data[addr] |= getBitMask(i);
} }
/**
* Set bit at the given index to 'false'.
*
* @param i the index
*/
public void clear(int i) { public void clear(int i) {
int addr = getAddress(i); int addr = getAddress(i);
if (addr >= data.length) { if (addr >= data.length) {
...@@ -107,6 +146,12 @@ public class BitField { ...@@ -107,6 +146,12 @@ public class BitField {
} }
} }
/**
* Enable or disable a number of bits.
*
* @param start the index of the first bit to enable or disable
* @param len the number of bits to enable or disable
*/
public void setRange(int start, int len, boolean value) { public void setRange(int start, int len, boolean value) {
for (int end = start + len; start < end; start++) { for (int end = start + len; start < end; start++) {
set(start, value); set(start, value);
......
...@@ -132,6 +132,13 @@ public class CompareMode { ...@@ -132,6 +132,13 @@ public class CompareMode {
return name.equalsIgnoreCase(locale.toString()) || name.equalsIgnoreCase(getName(locale)); return name.equalsIgnoreCase(locale.toString()) || name.equalsIgnoreCase(getName(locale));
} }
/**
* Get the collator object for the given language name or language / country
* combination.
*
* @param name the language name
* @return the collator
*/
public static Collator getCollator(String name) { public static Collator getCollator(String name) {
Collator result = null; Collator result = null;
if (name.length() == 2) { if (name.length() == 2) {
......
...@@ -37,10 +37,16 @@ import org.h2.util.StringUtils; ...@@ -37,10 +37,16 @@ import org.h2.util.StringUtils;
*/ */
public class DataType { public class DataType {
// JDK 1.3 compatibility: Types.BOOLEAN /**
* This constant is used for JDK 1.3 compatibility
* and equal to java.sql.Types.BOOLEAN
*/
public static final int TYPE_BOOLEAN = 16; public static final int TYPE_BOOLEAN = 16;
// JDK 1.3 compatibility: Types.DATALINK /**
* This constant is used for JDK 1.3 compatibility
* and equal to java.sql.Types.DATALINK
*/
public static final int TYPE_DATALINK = 70; public static final int TYPE_DATALINK = 70;
private static ObjectArray types = new ObjectArray(); private static ObjectArray types = new ObjectArray();
...@@ -316,6 +322,11 @@ public class DataType { ...@@ -316,6 +322,11 @@ public class DataType {
return dataType; return dataType;
} }
/**
* Get the list of data types.
*
* @return the list
*/
public static ObjectArray getTypes() { public static ObjectArray getTypes() {
return types; return types;
} }
...@@ -464,6 +475,12 @@ public class DataType { ...@@ -464,6 +475,12 @@ public class DataType {
return v; return v;
} }
/**
* Get the name of the Java class for the given value type.
*
* @param type the value type
* @return the class name
*/
public static String getTypeClassName(int type) { public static String getTypeClassName(int type) {
switch(type) { switch(type) {
case Value.BOOLEAN: case Value.BOOLEAN:
...@@ -531,6 +548,12 @@ public class DataType { ...@@ -531,6 +548,12 @@ public class DataType {
} }
} }
/**
* Get the data type object for the given value type.
*
* @param type the value type
* @return the data type object
*/
public static DataType getDataType(int type) { public static DataType getDataType(int type) {
DataType dt = typesByValueType[type]; DataType dt = typesByValueType[type];
if (dt == null) { if (dt == null) {
...@@ -539,10 +562,22 @@ public class DataType { ...@@ -539,10 +562,22 @@ public class DataType {
return dt; return dt;
} }
/**
* Convert a value type to a SQL type.
*
* @param type the value type
* @return the SQL type
*/
public static int convertTypeToSQLType(int type) { public static int convertTypeToSQLType(int type) {
return getDataType(type).sqlType; return getDataType(type).sqlType;
} }
/**
* Convert a SQL type to a value type.
*
* @param the SQL type
* @return type the value type
*/
public static int convertSQLTypeToValueType(int sqlType) throws SQLException { public static int convertSQLTypeToValueType(int sqlType) throws SQLException {
switch(sqlType) { switch(sqlType) {
case Types.CHAR: case Types.CHAR:
...@@ -595,6 +630,12 @@ public class DataType { ...@@ -595,6 +630,12 @@ public class DataType {
} }
} }
/**
* Get the value type for the given Java class.
*
* @param x the Java class
* @return the value type
*/
public static int getTypeFromClass(Class x) throws SQLException { public static int getTypeFromClass(Class x) throws SQLException {
// TODO refactor: too many if/else in functions, can reduce! // TODO refactor: too many if/else in functions, can reduce!
if (x == null) { if (x == null) {
...@@ -649,6 +690,14 @@ public class DataType { ...@@ -649,6 +690,14 @@ public class DataType {
} }
} }
/**
* Convert a Java object to a value.
*
* @param session the session
* @param x the value
* @param type the value type
* @return the value
*/
public static Value convertToValue(SessionInterface session, Object x, int type) throws SQLException { public static Value convertToValue(SessionInterface session, Object x, int type) throws SQLException {
if (x == null) { if (x == null) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
...@@ -717,10 +766,22 @@ public class DataType { ...@@ -717,10 +766,22 @@ public class DataType {
} }
} }
/**
* Get a data type object from a type name.
*
* @param s the type name
* @return the data type object
*/
public static DataType getTypeByName(String s) { public static DataType getTypeByName(String s) {
return (DataType) typesByName.get(s); return (DataType) typesByName.get(s);
} }
/**
* Check if the given value type is a large object (BLOB or CLOB).
*
* @param type the value type
* @return true if the value type is a lob type
*/
public static boolean isLargeObject(int type) { public static boolean isLargeObject(int type) {
if (type == Value.BLOB || type == Value.CLOB) { if (type == Value.BLOB || type == Value.CLOB) {
return true; return true;
...@@ -728,6 +789,12 @@ public class DataType { ...@@ -728,6 +789,12 @@ public class DataType {
return false; return false;
} }
/**
* Check if the given value type supports the add operation.
*
* @param type the value type
* @return true if add is supported
*/
public static boolean supportsAdd(int type) { public static boolean supportsAdd(int type) {
switch (type) { switch (type) {
case Value.BYTE: case Value.BYTE:
...@@ -743,6 +810,12 @@ public class DataType { ...@@ -743,6 +810,12 @@ public class DataType {
} }
} }
/**
* Get the default value in the form of a Java object for the given Java class.
*
* @param clazz the Java class
* @return the default object
*/
public static Object getDefaultForPrimitiveType(Class clazz) { public static Object getDefaultForPrimitiveType(Class clazz) {
if (clazz == Boolean.TYPE) { if (clazz == Boolean.TYPE) {
return Boolean.FALSE; return Boolean.FALSE;
......
...@@ -47,84 +47,172 @@ public class Transfer { ...@@ -47,84 +47,172 @@ public class Transfer {
private static final int BUFFER_SIZE = 16 * 1024; private static final int BUFFER_SIZE = 16 * 1024;
private static final int LOB_MAGIC = 0x1234; private static final int LOB_MAGIC = 0x1234;
protected Socket socket; private Socket socket;
protected DataInputStream in; private DataInputStream in;
protected DataOutputStream out; private DataOutputStream out;
private SessionInterface session; private SessionInterface session;
private boolean ssl; private boolean ssl;
/**
* Create a new transfer object for the specified session.
*
* @param session the session
*/
public Transfer(SessionInterface session) { public Transfer(SessionInterface session) {
this.session = session; this.session = session;
} }
/**
* Set the socket this object uses.
*
* @param s the socket
*/
public void setSocket(Socket s) { public void setSocket(Socket s) {
socket = s; socket = s;
} }
/**
* Initialize the transfer object. This method will try to open an input and
* output stream.
*/
public void init() throws IOException { public void init() throws IOException {
in = new DataInputStream(new BufferedInputStream(socket.getInputStream(), Transfer.BUFFER_SIZE)); in = new DataInputStream(new BufferedInputStream(socket.getInputStream(), Transfer.BUFFER_SIZE));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), Transfer.BUFFER_SIZE)); out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), Transfer.BUFFER_SIZE));
} }
/**
* Write pending changes.
*/
public void flush() throws IOException { public void flush() throws IOException {
out.flush(); out.flush();
} }
/**
* Write a boolean.
*
* @param x the value
* @return itself
*/
public Transfer writeBoolean(boolean x) throws IOException { public Transfer writeBoolean(boolean x) throws IOException {
out.writeByte((byte) (x ? 1 : 0)); out.writeByte((byte) (x ? 1 : 0));
return this; return this;
} }
/**
* Read a boolean.
*
* @return the value
*/
public boolean readBoolean() throws IOException { public boolean readBoolean() throws IOException {
return in.readByte() == 1; return in.readByte() == 1;
} }
public Transfer writeByte(byte x) throws IOException { /**
* Write a byte.
*
* @param x the value
* @return itself
*/
private Transfer writeByte(byte x) throws IOException {
out.writeByte(x); out.writeByte(x);
return this; return this;
} }
public byte readByte() throws IOException { /**
* Read a byte.
*
* @return the value
*/
private byte readByte() throws IOException {
return in.readByte(); return in.readByte();
} }
/**
* Write an int.
*
* @param x the value
* @return itself
*/
public Transfer writeInt(int i) throws IOException { public Transfer writeInt(int i) throws IOException {
out.writeInt(i); out.writeInt(i);
return this; return this;
} }
/**
* Read an int.
*
* @return the value
*/
public int readInt() throws IOException { public int readInt() throws IOException {
return in.readInt(); return in.readInt();
} }
/**
* Write a long.
*
* @param x the value
* @return itself
*/
public Transfer writeLong(long i) throws IOException { public Transfer writeLong(long i) throws IOException {
out.writeLong(i); out.writeLong(i);
return this; return this;
} }
/**
* Read a long.
*
* @return the value
*/
public long readLong() throws IOException { public long readLong() throws IOException {
return in.readLong(); return in.readLong();
} }
public Transfer writeDouble(double i) throws IOException { /**
* Write a double.
*
* @param x the value
* @return itself
*/
private Transfer writeDouble(double i) throws IOException {
out.writeDouble(i); out.writeDouble(i);
return this; return this;
} }
public Transfer writeFloat(float i) throws IOException { /**
* Write a float.
*
* @param x the value
* @return itself
*/
private Transfer writeFloat(float i) throws IOException {
out.writeFloat(i); out.writeFloat(i);
return this; return this;
} }
public double readDouble() throws IOException { /**
* Read a double.
*
* @return the value
*/
private double readDouble() throws IOException {
return in.readDouble(); return in.readDouble();
} }
public float readFloat() throws IOException { /**
* Read a float.
*
* @return the value
*/
private float readFloat() throws IOException {
return in.readFloat(); return in.readFloat();
} }
/**
* Write a string. The maximum string length is Integer.MAX_VALUE.
*
* @param s the value
* @return itself
*/
public Transfer writeString(String s) throws IOException { public Transfer writeString(String s) throws IOException {
if (s == null) { if (s == null) {
out.writeInt(-1); out.writeInt(-1);
...@@ -138,6 +226,11 @@ public class Transfer { ...@@ -138,6 +226,11 @@ public class Transfer {
return this; return this;
} }
/**
* Read a string.
*
* @return the value
*/
public String readString() throws IOException { public String readString() throws IOException {
int len = in.readInt(); int len = in.readInt();
if (len == -1) { if (len == -1) {
...@@ -154,6 +247,12 @@ public class Transfer { ...@@ -154,6 +247,12 @@ public class Transfer {
return s; return s;
} }
/**
* Write a byte array.
*
* @param data the value
* @return itself
*/
public Transfer writeBytes(byte[] data) throws IOException { public Transfer writeBytes(byte[] data) throws IOException {
if (data == null) { if (data == null) {
writeInt(-1); writeInt(-1);
...@@ -164,6 +263,11 @@ public class Transfer { ...@@ -164,6 +263,11 @@ public class Transfer {
return this; return this;
} }
/**
* Read a byte array.
*
* @return the value
*/
public byte[] readBytes() throws IOException { public byte[] readBytes() throws IOException {
int len = readInt(); int len = readInt();
if (len == -1) { if (len == -1) {
...@@ -174,6 +278,9 @@ public class Transfer { ...@@ -174,6 +278,9 @@ public class Transfer {
return b; return b;
} }
/**
* Close the transfer object and the socket.
*/
public void close() { public void close() {
if (socket != null) { if (socket != null) {
try { try {
...@@ -189,6 +296,11 @@ public class Transfer { ...@@ -189,6 +296,11 @@ public class Transfer {
} }
} }
/**
* Write a value.
*
* @param v the value
*/
public void writeValue(Value v) throws IOException, SQLException { public void writeValue(Value v) throws IOException, SQLException {
int type = v.getType(); int type = v.getType();
writeInt(type); writeInt(type);
...@@ -321,6 +433,11 @@ public class Transfer { ...@@ -321,6 +433,11 @@ public class Transfer {
} }
} }
/**
* Read a value.
*
* @return the value
*/
public Value readValue() throws IOException, SQLException { public Value readValue() throws IOException, SQLException {
int type = readInt(); int type = readInt();
switch(type) { switch(type) {
...@@ -410,18 +527,38 @@ public class Transfer { ...@@ -410,18 +527,38 @@ public class Transfer {
} }
} }
/**
* Get the socket.
*
* @return the socket
*/
public Socket getSocket() { public Socket getSocket() {
return socket; return socket;
} }
/**
* Set the session.
*
* @param session the session
*/
public void setSession(SessionInterface session) { public void setSession(SessionInterface session) {
this.session = session; this.session = session;
} }
/**
* Enable or disable SSL.
*
* @param ssl the new value
*/
public void setSSL(boolean ssl) { public void setSSL(boolean ssl) {
this.ssl = ssl; this.ssl = ssl;
} }
/**
* Open a new new connection to the same address and port as this one.
*
* @return the new transfer object
*/
public Transfer openNewConnection() throws IOException { public Transfer openNewConnection() throws IOException {
InetAddress address = socket.getInetAddress(); InetAddress address = socket.getInetAddress();
int port = socket.getPort(); int port = socket.getPort();
......
...@@ -39,11 +39,119 @@ public abstract class Value { ...@@ -39,11 +39,119 @@ public abstract class Value {
* The data type is unknown at this time. * The data type is unknown at this time.
*/ */
public static final int UNKNOWN = -1; public static final int UNKNOWN = -1;
public static final int NULL = 0, BOOLEAN = 1, BYTE = 2, SHORT = 3, INT = 4, LONG = 5, DECIMAL = 6;
public static final int DOUBLE = 7, FLOAT = 8, TIME = 9, DATE = 10, TIMESTAMP = 11, BYTES = 12;
public static final int STRING = 13, STRING_IGNORECASE = 14, BLOB = 15, CLOB = 16;
public static final int ARRAY = 17, RESULT_SET = 18, JAVA_OBJECT = 19, UUID = 20, STRING_FIXED = 21;
/**
* The value type for NULL.
*/
public static final int NULL = 0;
/**
* The value type for BOOLEAN values.
*/
public static final int BOOLEAN = 1;
/**
* The value type for BYTE values.
*/
public static final int BYTE = 2;
/**
* The value type for SHORT values.
*/
public static final int SHORT = 3;
/**
* The value type for INT values.
*/
public static final int INT = 4;
/**
* The value type for LONG values.
*/
public static final int LONG = 5;
/**
* The value type for DECIMAL values.
*/
public static final int DECIMAL = 6;
/**
* The value type for DOUBLE values.
*/
public static final int DOUBLE = 7;
/**
* The value type for FLOAT values.
*/
public static final int FLOAT = 8;
/**
* The value type for INT values.
*/
public static final int TIME = 9;
/**
* The value type for DATE values.
*/
public static final int DATE = 10;
/**
* The value type for TIMESTAMP values.
*/
public static final int TIMESTAMP = 11;
/**
* The value type for BYTES values.
*/
public static final int BYTES = 12;
/**
* The value type for STRING values.
*/
public static final int STRING = 13;
/**
* The value type for case insensitive STRING values.
*/
public static final int STRING_IGNORECASE = 14;
/**
* The value type for BLOB values.
*/
public static final int BLOB = 15;
/**
* The value type for CLOB values.
*/
public static final int CLOB = 16;
/**
* The value type for ARRAY values.
*/
public static final int ARRAY = 17;
/**
* The value type for RESULT_SET values.
*/
public static final int RESULT_SET = 18;
/**
* The value type for JAVA_OBJECT values.
*/
public static final int JAVA_OBJECT = 19;
/**
* The value type for UUID values.
*/
public static final int UUID = 20;
/**
* The value type for string values with a fixed size.
*/
public static final int STRING_FIXED = 21;
/**
* The number of value types.
*/
public static final int TYPE_COUNT = STRING_FIXED + 1; public static final int TYPE_COUNT = STRING_FIXED + 1;
private static SoftReference softCache = new SoftReference(null); private static SoftReference softCache = new SoftReference(null);
...@@ -131,7 +239,13 @@ public abstract class Value { ...@@ -131,7 +239,13 @@ public abstract class Value {
*/ */
public abstract boolean equals(Object other); public abstract boolean equals(Object other);
public static int getOrder(int type) { /**
* Get the order of this value type.
*
* @param type the value type
* @return the order number
*/
static int getOrder(int type) {
switch(type) { switch(type) {
case UNKNOWN: case UNKNOWN:
return 1; return 1;
...@@ -184,6 +298,15 @@ public abstract class Value { ...@@ -184,6 +298,15 @@ public abstract class Value {
} }
} }
/**
* Get the higher value order type of two value types. If values need to be
* converted to match the other operands value type, the value with the
* lower order is converted to the value with the higher order.
*
* @param t1 the first value type
* @param t2 the second value type
* @return the higher value type of the two
*/
public static int getHigherOrder(int t1, int t2) throws SQLException { public static int getHigherOrder(int t1, int t2) throws SQLException {
if (t1 == t2) { if (t1 == t2) {
if (t1 == Value.UNKNOWN) { if (t1 == Value.UNKNOWN) {
...@@ -306,6 +429,11 @@ public abstract class Value { ...@@ -306,6 +429,11 @@ public abstract class Value {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
/**
* Return -value if this value support arithmetic operations.
*
* @return the negative
*/
public Value negate() throws SQLException { public Value negate() throws SQLException {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
...@@ -340,6 +468,12 @@ public abstract class Value { ...@@ -340,6 +468,12 @@ public abstract class Value {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
/**
* Compare a value to the specified type.
*
* @param type the value type
* @return the value
*/
public Value convertTo(int type) throws SQLException { public Value convertTo(int type) throws SQLException {
// converting NULL done in ValueNull // converting NULL done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob // converting BLOB to CLOB and vice versa is done in ValueLob
...@@ -641,6 +775,15 @@ public abstract class Value { ...@@ -641,6 +775,15 @@ public abstract class Value {
} }
} }
/**
* Compare this value against another value given that the values are of the
* same data type.
*
* @param v the other value
* @param mode the compare mode
* @return 0 if both values are equal, -1 if the other value is smaller, and
* 1 otherwise
*/
public final int compareTypeSave(Value v, CompareMode mode) throws SQLException { public final int compareTypeSave(Value v, CompareMode mode) throws SQLException {
if (this == ValueNull.INSTANCE) { if (this == ValueNull.INSTANCE) {
return v == ValueNull.INSTANCE ? 0 : -1; return v == ValueNull.INSTANCE ? 0 : -1;
...@@ -650,6 +793,12 @@ public abstract class Value { ...@@ -650,6 +793,12 @@ public abstract class Value {
return compareSecure(v, mode); return compareSecure(v, mode);
} }
/**
* Compare two values and return true if they contain the same data.
*
* @param v the value to compare against
* @return true if both values are the same * @throws SQLException
*/
public final boolean compareEqual(Value v) throws SQLException { public final boolean compareEqual(Value v) throws SQLException {
if (this == ValueNull.INSTANCE) { if (this == ValueNull.INSTANCE) {
return v == ValueNull.INSTANCE; return v == ValueNull.INSTANCE;
...@@ -663,6 +812,15 @@ public abstract class Value { ...@@ -663,6 +812,15 @@ public abstract class Value {
return convertTo(t2).equals(v.convertTo(t2)); return convertTo(t2).equals(v.convertTo(t2));
} }
/**
* Compare this value against another value using the specified compare
* mode.
*
* @param v the other value
* @param mode the compare mode
* @return 0 if both values are equal, -1 if the other value is smaller, and
* 1 otherwise
*/
public final int compareTo(Value v, CompareMode mode) throws SQLException { public final int compareTo(Value v, CompareMode mode) throws SQLException {
if (this == ValueNull.INSTANCE) { if (this == ValueNull.INSTANCE) {
return v == ValueNull.INSTANCE ? 0 : -1; return v == ValueNull.INSTANCE ? 0 : -1;
...@@ -744,7 +902,8 @@ public abstract class Value { ...@@ -744,7 +902,8 @@ public abstract class Value {
} }
/** /**
* Link a large value to a given table. * Link a large value to a given table. For values that are kept fully in
* memory this method has no effect.
* *
* @param handler the data handler * @param handler the data handler
* @param tableId the table to link to * @param tableId the table to link to
...@@ -754,22 +913,49 @@ public abstract class Value { ...@@ -754,22 +913,49 @@ public abstract class Value {
return this; return this;
} }
/**
* Check if this value is linked to a specific table. For values that are
* kept fully in memory, this method returns false.
*
* @return true if it is
*/
public boolean isLinked() { public boolean isLinked() {
return false; return false;
} }
/**
* Mark any underlying resource as 'not linked to any table'. For values
* that are kept fully in memory this method has no effect.
*/
public void unlink() throws SQLException { public void unlink() throws SQLException {
// nothing to do // nothing to do
} }
/**
* Check if this value is stored in it's own file. For values that are
* kept fully in memory, this method returns false.
*
* @return true if it is
*/
public boolean isFileBased() { public boolean isFileBased() {
return false; return false;
} }
/**
* Close the underlying resource, if any. For values that are kept fully in
* memory this method has no effect.
*/
public void close() throws SQLException { public void close() throws SQLException {
// nothing to do // nothing to do
} }
/**
* Check if the precision is smaller or equal than the given precision.
*
* @param precision the maximum precision
* @return true if the precision of this value is smaller or equal to the
* given precision
*/
public boolean checkPrecision(long precision) { public boolean checkPrecision(long precision) {
return getPrecision() <= precision; return getPrecision() <= precision;
} }
......
...@@ -23,6 +23,13 @@ public class ValueArray extends Value { ...@@ -23,6 +23,13 @@ public class ValueArray extends Value {
this.values = list; this.values = list;
} }
/**
* Get or create a array value for the given value array.
* Do not clone the data.
*
* @param list the value array
* @return the value
*/
public static ValueArray get(Value[] list) { public static ValueArray get(Value[] list) {
return new ValueArray(list); return new ValueArray(list);
} }
......
...@@ -13,8 +13,16 @@ import java.sql.SQLException; ...@@ -13,8 +13,16 @@ import java.sql.SQLException;
* Implementation of the BOOLEAN data type. * Implementation of the BOOLEAN data type.
*/ */
public class ValueBoolean extends Value { public class ValueBoolean extends Value {
/**
* The precision in digits.
*/
public static final int PRECISION = 1; public static final int PRECISION = 1;
// "FALSE".length()
/**
* The maximum display size of a boolean.
* Example: FALSE
*/
public static final int DISPLAY_SIZE = 5; public static final int DISPLAY_SIZE = 5;
private static final ValueBoolean TRUE = new ValueBoolean(true); private static final ValueBoolean TRUE = new ValueBoolean(true);
...@@ -68,6 +76,12 @@ public class ValueBoolean extends Value { ...@@ -68,6 +76,12 @@ public class ValueBoolean extends Value {
prep.setBoolean(parameterIndex, value.booleanValue()); prep.setBoolean(parameterIndex, value.booleanValue());
} }
/**
* Get the boolean value for the given boolean.
*
* @param b the boolean
* @return the value
*/
public static ValueBoolean get(boolean b) { public static ValueBoolean get(boolean b) {
return b ? TRUE : FALSE; return b ? TRUE : FALSE;
} }
......
...@@ -18,8 +18,12 @@ import org.h2.util.ObjectUtils; ...@@ -18,8 +18,12 @@ import org.h2.util.ObjectUtils;
* Implementation of the BYTE data type. * Implementation of the BYTE data type.
*/ */
public class ValueByte extends Value { public class ValueByte extends Value {
public static final int PRECISION = 3;
public static final int DISPLAY_SIZE = 4; /**
* The precision in digits.
*/
static final int PRECISION = 3;
static final int DISPLAY_SIZE = 4;
private final byte value; private final byte value;
...@@ -117,6 +121,12 @@ public class ValueByte extends Value { ...@@ -117,6 +121,12 @@ public class ValueByte extends Value {
prep.setByte(parameterIndex, value); prep.setByte(parameterIndex, value);
} }
/**
* Get or create byte value for the given byte.
*
* @param i the byte
* @return the value
*/
public static ValueByte get(byte i) { public static ValueByte get(byte i) {
return (ValueByte) Value.cache(new ValueByte(i)); return (ValueByte) Value.cache(new ValueByte(i));
} }
......
...@@ -20,11 +20,28 @@ public class ValueBytes extends ValueBytesBase { ...@@ -20,11 +20,28 @@ public class ValueBytes extends ValueBytesBase {
super(v); super(v);
} }
/**
* Get or create a bytes value for the given byte array.
* Clone the data.
*
* @param b the byte array
* @return the value
*/
public static ValueBytes get(byte[] b) { public static ValueBytes get(byte[] b) {
if (b.length == 0) {
return EMPTY;
}
b = ByteUtils.cloneByteArray(b); b = ByteUtils.cloneByteArray(b);
return getNoCopy(b); return getNoCopy(b);
} }
/**
* Get or create a bytes value for the given byte array.
* Do not clone the date.
*
* @param b the byte array
* @return the value
*/
public static ValueBytes getNoCopy(byte[] b) { public static ValueBytes getNoCopy(byte[] b) {
if (b.length == 0) { if (b.length == 0) {
return EMPTY; return EMPTY;
......
...@@ -18,9 +18,13 @@ import org.h2.util.DateTimeUtils; ...@@ -18,9 +18,13 @@ import org.h2.util.DateTimeUtils;
* Implementation of the DATE data type. * Implementation of the DATE data type.
*/ */
public class ValueDate extends Value { public class ValueDate extends Value {
public static final int PRECISION = 8; static final int PRECISION = 8;
// "2000-01-02".length()
public static final int DISPLAY_SIZE = 10; /**
* The display size of the textual representation of a date.
* Example: 2000-01-02
*/
static final int DISPLAY_SIZE = 10;
private final Date value; private final Date value;
...@@ -28,6 +32,12 @@ public class ValueDate extends Value { ...@@ -28,6 +32,12 @@ public class ValueDate extends Value {
this.value = value; this.value = value;
} }
/**
* Parse a string to a java.sql.Date object.
*
* @param s the string to parse
* @return the date
*/
public static Date parseDate(String s) throws SQLException { public static Date parseDate(String s) throws SQLException {
return (Date) DateTimeUtils.parseDateTime(s, Value.DATE, ErrorCode.DATE_CONSTANT_2); return (Date) DateTimeUtils.parseDateTime(s, Value.DATE, ErrorCode.DATE_CONSTANT_2);
} }
...@@ -86,11 +96,25 @@ public class ValueDate extends Value { ...@@ -86,11 +96,25 @@ public class ValueDate extends Value {
prep.setDate(parameterIndex, value); prep.setDate(parameterIndex, value);
} }
/**
* Get or create a date value for the given date.
* Clone the date.
*
* @param date the date
* @return the value
*/
public static ValueDate get(Date date) { public static ValueDate get(Date date) {
date = DateTimeUtils.cloneAndNormalizeDate(date); date = DateTimeUtils.cloneAndNormalizeDate(date);
return getNoCopy(date); return getNoCopy(date);
} }
/**
* Get or create a date value for the given date.
* Do not clone the date.
*
* @param date the date
* @return the value
*/
public static ValueDate getNoCopy(Date date) { public static ValueDate getNoCopy(Date date) {
return (ValueDate) Value.cache(new ValueDate(date)); return (ValueDate) Value.cache(new ValueDate(date));
} }
......
...@@ -20,9 +20,9 @@ import org.h2.util.MathUtils; ...@@ -20,9 +20,9 @@ import org.h2.util.MathUtils;
*/ */
public class ValueDecimal extends Value { public class ValueDecimal extends Value {
public static final int DEFAULT_PRECISION = 65535; static final int DEFAULT_PRECISION = 65535;
public static final int DEFAULT_SCALE = 32767; static final int DEFAULT_SCALE = 32767;
public static final int DEFAULT_DISPLAY_SIZE = 65535; static final int DEFAULT_DISPLAY_SIZE = 65535;
private static final int DIVIDE_SCALE_ADD = 25; private static final int DIVIDE_SCALE_ADD = 25;
private static final BigDecimal DEC_ZERO = new BigDecimal("0"); private static final BigDecimal DEC_ZERO = new BigDecimal("0");
...@@ -169,6 +169,12 @@ public class ValueDecimal extends Value { ...@@ -169,6 +169,12 @@ public class ValueDecimal extends Value {
throw Message.getSQLException(ErrorCode.VALUE_TOO_LARGE_FOR_PRECISION_1, "" + precision); throw Message.getSQLException(ErrorCode.VALUE_TOO_LARGE_FOR_PRECISION_1, "" + precision);
} }
/**
* Get or create big decimal value for the given big decimal.
*
* @param dec the bit decimal
* @return the value
*/
public static ValueDecimal get(BigDecimal dec) { public static ValueDecimal get(BigDecimal dec) {
if (DEC_ZERO.equals(dec)) { if (DEC_ZERO.equals(dec)) {
return ZERO; return ZERO;
......
...@@ -17,8 +17,16 @@ import org.h2.util.ObjectUtils; ...@@ -17,8 +17,16 @@ import org.h2.util.ObjectUtils;
* Implementation of the DOUBLE data type. * Implementation of the DOUBLE data type.
*/ */
public class ValueDouble extends Value { public class ValueDouble extends Value {
/**
* The precision in digits.
*/
public static final int PRECISION = 17; public static final int PRECISION = 17;
// "-3.3333333333333334E-100".length()
/**
* The maximum display size of a double.
* Example: -3.3333333333333334E-100
*/
public static final int DISPLAY_SIZE = 24; public static final int DISPLAY_SIZE = 24;
private static final double DOUBLE_ZERO = 0.0; private static final double DOUBLE_ZERO = 0.0;
...@@ -114,6 +122,12 @@ public class ValueDouble extends Value { ...@@ -114,6 +122,12 @@ public class ValueDouble extends Value {
prep.setDouble(parameterIndex, value); prep.setDouble(parameterIndex, value);
} }
/**
* Get or create double value for the given double.
*
* @param d the double
* @return the value
*/
public static ValueDouble get(double d) { public static ValueDouble get(double d) {
if (DOUBLE_ZERO == d) { if (DOUBLE_ZERO == d) {
return ZERO; return ZERO;
......
...@@ -17,9 +17,13 @@ import org.h2.util.ObjectUtils; ...@@ -17,9 +17,13 @@ import org.h2.util.ObjectUtils;
* Implementation of the REAL data type. * Implementation of the REAL data type.
*/ */
public class ValueFloat extends Value { public class ValueFloat extends Value {
public static final int PRECISION = 7; static final int PRECISION = 7;
// "-1.12345676E-20".length()
public static final int DISPLAY_SIZE = 15; /**
* The maximum display size of a float.
* Example: -1.12345676E-20
*/
static final int DISPLAY_SIZE = 15;
private static final float FLOAT_ZERO = 0.0F; private static final float FLOAT_ZERO = 0.0F;
private static final float FLOAT_ONE = 1.0F; private static final float FLOAT_ONE = 1.0F;
...@@ -114,6 +118,12 @@ public class ValueFloat extends Value { ...@@ -114,6 +118,12 @@ public class ValueFloat extends Value {
prep.setFloat(parameterIndex, value); prep.setFloat(parameterIndex, value);
} }
/**
* Get or create float value for the given float.
*
* @param d the float
* @return the value
*/
public static ValueFloat get(float d) { public static ValueFloat get(float d) {
if (FLOAT_ZERO == d) { if (FLOAT_ZERO == d) {
return ZERO; return ZERO;
......
...@@ -18,8 +18,16 @@ import org.h2.util.ObjectUtils; ...@@ -18,8 +18,16 @@ import org.h2.util.ObjectUtils;
* Implementation of the INT data type. * Implementation of the INT data type.
*/ */
public class ValueInt extends Value { public class ValueInt extends Value {
/**
* The precision in digits.
*/
public static final int PRECISION = 10; public static final int PRECISION = 10;
// "-2147483648".length()
/**
* The maximum display size of an int.
* Example: -2147483648
*/
public static final int DISPLAY_SIZE = 11; public static final int DISPLAY_SIZE = 11;
private static final int STATIC_SIZE = 100; private static final int STATIC_SIZE = 100;
...@@ -43,6 +51,12 @@ public class ValueInt extends Value { ...@@ -43,6 +51,12 @@ public class ValueInt extends Value {
this.value = value; this.value = value;
} }
/**
* Get or create an int value for the given int.
*
* @param i the int
* @return the value
*/
public static ValueInt get(int i) { public static ValueInt get(int i) {
if (i >= 0 && i < STATIC_SIZE) { if (i >= 0 && i < STATIC_SIZE) {
return staticCache[i]; return staticCache[i];
......
...@@ -19,6 +19,13 @@ public class ValueJavaObject extends ValueBytesBase { ...@@ -19,6 +19,13 @@ public class ValueJavaObject extends ValueBytesBase {
super(v); super(v);
} }
/**
* Get or create a java object value for the given byte array.
* Do not clone the data.
*
* @param b the byte array
* @return the value
*/
public static ValueJavaObject getNoCopy(byte[] b) { public static ValueJavaObject getNoCopy(byte[] b) {
if (b.length == 0) { if (b.length == 0) {
return EMPTY; return EMPTY;
......
...@@ -31,22 +31,36 @@ import org.h2.util.SmallLRUCache; ...@@ -31,22 +31,36 @@ import org.h2.util.SmallLRUCache;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
* Implementation of the BLOB and CLOB data types. * Implementation of the BLOB and CLOB data types. Small objects are kept in
* memory and stored in the data page of the record.
*
* Large objects are stored in their own files. When large objects are set in a
* prepared statement, they are first stored as 'temporary' files. Later, when
* they are used in a record, and when the record is stored, the lob files are
* linked: the file is renamed using the file format (tableId).(objectId). There
* is one exception: large variables are stored in the file (-1).(objectId).
*
* When lobs are deleted, they are first renamed to a temp file, and if the
* delete operation is committed the file is deleted.
*
* Data compression is supported.
*/ */
public class ValueLob extends Value { public class ValueLob extends Value {
// TODO lob: concatenate function for blob and clob // TODO lob: concatenate function for blob and clob
// (to create a large blob from pieces) // (to create a large blob from pieces)
// and a getpart function (to get it in pieces) and make sure a file is created! // and a getpart function (to get it in pieces) and make sure a file is created!
public static final int TABLE_ID_SESSION = -1; /**
* The 'table id' to use for session variables.
*/
public static final int TABLE_ID_SESSION_VARIABLE = -1;
/** /**
* This counter is used to calculate the next directory to store lobs. * This counter is used to calculate the next directory to store lobs. It is
* It is better than using a random number because less directories are created. * better than using a random number because less directories are created.
*/ */
private static int dirCounter; private static int dirCounter;
private final int type; private final int type;
private long precision; private long precision;
private DataHandler handler; private DataHandler handler;
...@@ -90,6 +104,13 @@ public class ValueLob extends Value { ...@@ -90,6 +104,13 @@ public class ValueLob extends Value {
return copy; return copy;
} }
/**
* Create a small lob using the given byte array.
*
* @param type the type (Value.BLOB or CLOB)
* @param small the byte array
* @return the lob value
*/
public static ValueLob createSmallLob(int type, byte[] small) { public static ValueLob createSmallLob(int type, byte[] small) {
return new ValueLob(type, small); return new ValueLob(type, small);
} }
...@@ -121,6 +142,14 @@ public class ValueLob extends Value { ...@@ -121,6 +142,14 @@ public class ValueLob extends Value {
return new ValueLob(type, handler, fileName, tableId, objectId, true, precision, compression); return new ValueLob(type, handler, fileName, tableId, objectId, true, precision, compression);
} }
/**
* Create a CLOB value from a stream.
*
* @param in the reader
* @param length the number of characters to read, or -1 for no limit
* @param handler the data handler
* @return the lob value
*/
public static ValueLob createClob(Reader in, long length, DataHandler handler) throws SQLException { public static ValueLob createClob(Reader in, long length, DataHandler handler) throws SQLException {
try { try {
boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null; boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null;
...@@ -297,6 +326,14 @@ public class ValueLob extends Value { ...@@ -297,6 +326,14 @@ public class ValueLob extends Value {
return list; return list;
} }
/**
* Create a BLOB value from a stream.
*
* @param in the input stream
* @param length the number of characters to read, or -1 for no limit
* @param handler the data handler
* @return the lob value
*/
public static ValueLob createBlob(InputStream in, long length, DataHandler handler) throws SQLException { public static ValueLob createBlob(InputStream in, long length, DataHandler handler) throws SQLException {
try { try {
long remaining = Long.MAX_VALUE; long remaining = Long.MAX_VALUE;
...@@ -371,6 +408,13 @@ public class ValueLob extends Value { ...@@ -371,6 +408,13 @@ public class ValueLob extends Value {
} }
} }
/**
* Convert a lob to another data type. The data is fully read in memory
* except when converting to BLOB or CLOB.
*
* @param t the new type
* @return the converted value
*/
public Value convertTo(int t) throws SQLException { public Value convertTo(int t) throws SQLException {
if (t == type) { if (t == type) {
return this; return this;
...@@ -388,6 +432,11 @@ public class ValueLob extends Value { ...@@ -388,6 +432,11 @@ public class ValueLob extends Value {
return linked; return linked;
} }
/**
* Get the current file name where the lob is saved.
*
* @return the file name or null
*/
public String getFileName() { public String getFileName() {
return fileName; return fileName;
} }
...@@ -457,10 +506,20 @@ public class ValueLob extends Value { ...@@ -457,10 +506,20 @@ public class ValueLob extends Value {
return this; return this;
} }
/**
* Get the current table id of this lob.
*
* @return the table id
*/
public int getTableId() { public int getTableId() {
return tableId; return tableId;
} }
/**
* Get the current object id of this lob.
*
* @return the object id
*/
public int getObjectId() { public int getObjectId() {
return objectId; return objectId;
} }
...@@ -601,6 +660,11 @@ public class ValueLob extends Value { ...@@ -601,6 +660,11 @@ public class ValueLob extends Value {
return getSQL(); return getSQL();
} }
/**
* Get the data if this a small lob value.
*
* @return the data
*/
public byte[] getSmall() { public byte[] getSmall() {
return small; return small;
} }
...@@ -617,6 +681,12 @@ public class ValueLob extends Value { ...@@ -617,6 +681,12 @@ public class ValueLob extends Value {
} }
} }
/**
* Store the lob data to a file if the size of the buffer it larger than the
* maximum size for an in-place lob.
*
* @param handler the data handler
*/
public void convertToFileIfRequired(DataHandler handler) throws SQLException { public void convertToFileIfRequired(DataHandler handler) throws SQLException {
if (Constants.AUTO_CONVERT_LOB_TO_FILES && small != null && small.length > handler.getMaxLengthInplaceLob()) { if (Constants.AUTO_CONVERT_LOB_TO_FILES && small != null && small.length > handler.getMaxLengthInplaceLob()) {
boolean compress = handler.getLobCompressionAlgorithm(type) != null; boolean compress = handler.getLobCompressionAlgorithm(type) != null;
...@@ -634,6 +704,12 @@ public class ValueLob extends Value { ...@@ -634,6 +704,12 @@ public class ValueLob extends Value {
} }
} }
/**
* Remove all lobs for a given table id.
*
* @param handler the data handler
* @param tableId the table id
*/
public static void removeAllForTable(DataHandler handler, int tableId) throws SQLException { public static void removeAllForTable(DataHandler handler, int tableId) throws SQLException {
if (handler.getLobFilesInDirectories()) { if (handler.getLobFilesInDirectories()) {
String dir = getFileNamePrefix(handler.getDatabasePath(), 0); String dir = getFileNamePrefix(handler.getDatabasePath(), 0);
...@@ -665,6 +741,11 @@ public class ValueLob extends Value { ...@@ -665,6 +741,11 @@ public class ValueLob extends Value {
} }
} }
/**
* Check if this lob value is compressed.
*
* @return true if it is
*/
public boolean useCompression() { public boolean useCompression() {
return compression; return compression;
} }
...@@ -694,6 +775,12 @@ public class ValueLob extends Value { ...@@ -694,6 +775,12 @@ public class ValueLob extends Value {
} }
} }
/**
* Set the file name of this lob value.
*
* @param fileName the file name
* @param linked if the lob is linked
*/
public void setFileName(String fileName, boolean linked) { public void setFileName(String fileName, boolean linked) {
this.fileName = fileName; this.fileName = fileName;
this.linked = linked; this.linked = linked;
......
...@@ -20,9 +20,17 @@ import org.h2.util.ObjectUtils; ...@@ -20,9 +20,17 @@ import org.h2.util.ObjectUtils;
*/ */
public class ValueLong extends Value { public class ValueLong extends Value {
/**
* The precision in digits.
*/
public static final int PRECISION = 19; public static final int PRECISION = 19;
// "-9223372036854775808".length()
/**
* The maximum display size of a long.
* Example: 9223372036854775808
*/
public static final int DISPLAY_SIZE = 20; public static final int DISPLAY_SIZE = 20;
private static final int STATIC_SIZE = 10; private static final int STATIC_SIZE = 10;
private static ValueLong[] cache; private static ValueLong[] cache;
private static final BigInteger MIN = new BigInteger("" + Long.MIN_VALUE); private static final BigInteger MIN = new BigInteger("" + Long.MIN_VALUE);
...@@ -172,6 +180,12 @@ public class ValueLong extends Value { ...@@ -172,6 +180,12 @@ public class ValueLong extends Value {
prep.setLong(parameterIndex, value); prep.setLong(parameterIndex, value);
} }
/**
* Get or create a long value for the given long.
*
* @param i the long
* @return the value
*/
public static ValueLong get(long i) { public static ValueLong get(long i) {
if (i >= 0 && i < STATIC_SIZE) { if (i >= 0 && i < STATIC_SIZE) {
return cache[(int) i]; return cache[(int) i];
......
...@@ -22,12 +22,26 @@ import org.h2.message.Message; ...@@ -22,12 +22,26 @@ import org.h2.message.Message;
*/ */
public class ValueNull extends Value { public class ValueNull extends Value {
/**
* The main NULL instance.
*/
public static final ValueNull INSTANCE = new ValueNull(); public static final ValueNull INSTANCE = new ValueNull();
/**
* This special instance is used as a marker for deleted entries in a map.
* It should not be used anywhere else.
*/
public static final ValueNull DELETED = new ValueNull(); public static final ValueNull DELETED = new ValueNull();
public static final int PRECISION = 1; /**
// "null".length() * The precision of NULL.
public static final int DISPLAY_SIZE = 4; */
private static final int PRECISION = 1;
/**
* The display size of the textual representation of NULL.
*/
private static final int DISPLAY_SIZE = 4;
private ValueNull() { private ValueNull() {
// don't allow construction // don't allow construction
......
...@@ -25,11 +25,27 @@ public class ValueResultSet extends Value { ...@@ -25,11 +25,27 @@ public class ValueResultSet extends Value {
this.result = rs; this.result = rs;
} }
/**
* Create a result set value for the given result set.
* The result set will be wrapped.
*
* @param rs the result set
* @return the value
*/
public static ValueResultSet get(ResultSet rs) { public static ValueResultSet get(ResultSet rs) {
ValueResultSet val = new ValueResultSet(rs); ValueResultSet val = new ValueResultSet(rs);
return val; return val;
} }
/**
* Create a result set value for the given result set. The result set will
* be fully read in memory.
*
* @param rs the result set
* @param maxrows the maximum number of rows to read (0 to just read the
* meta data)
* @return the value
*/
public static ValueResultSet getCopy(ResultSet rs, int maxrows) throws SQLException { public static ValueResultSet getCopy(ResultSet rs, int maxrows) throws SQLException {
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount(); int columnCount = meta.getColumnCount();
......
...@@ -19,9 +19,13 @@ import org.h2.util.ObjectUtils; ...@@ -19,9 +19,13 @@ import org.h2.util.ObjectUtils;
*/ */
public class ValueShort extends Value { public class ValueShort extends Value {
public static final int PRECISION = 5; static final int PRECISION = 5;
// "-32768".length()
public static final int DISPLAY_SIZE = 6; /**
* The maximum display size of a short.
* Example: -32768
*/
static final int DISPLAY_SIZE = 6;
private final short value; private final short value;
...@@ -119,6 +123,12 @@ public class ValueShort extends Value { ...@@ -119,6 +123,12 @@ public class ValueShort extends Value {
prep.setShort(parameterIndex, value); prep.setShort(parameterIndex, value);
} }
/**
* Get or create a short value for the given short.
*
* @param i the short
* @return the value
*/
public static ValueShort get(short i) { public static ValueShort get(short i) {
return (ValueShort) Value.cache(new ValueShort(i)); return (ValueShort) Value.cache(new ValueShort(i));
} }
......
...@@ -74,6 +74,12 @@ public class ValueString extends ValueStringBase { ...@@ -74,6 +74,12 @@ public class ValueString extends ValueStringBase {
return ValueString.get(value.substring(0, p)); return ValueString.get(value.substring(0, p));
} }
/**
* Get or create a string value for the given string.
*
* @param s the string
* @return the value
*/
public static ValueString get(String s) { public static ValueString get(String s) {
if (s.length() == 0) { if (s.length() == 0) {
return EMPTY; return EMPTY;
......
...@@ -51,11 +51,18 @@ public class ValueStringFixed extends ValueStringBase { ...@@ -51,11 +51,18 @@ public class ValueStringFixed extends ValueStringBase {
return Value.STRING_FIXED; return Value.STRING_FIXED;
} }
/**
* Get or create a fixed length string value for the given string.
* Spaces at the end of the string will be removed.
*
* @param s the string
* @return the value
*/
public static ValueStringFixed get(String s) { public static ValueStringFixed get(String s) {
s = trimRight(s);
if (s.length() == 0) { if (s.length() == 0) {
return EMPTY; return EMPTY;
} }
s = trimRight(s);
ValueStringFixed obj = new ValueStringFixed(StringCache.get(s)); ValueStringFixed obj = new ValueStringFixed(StringCache.get(s));
if (s.length() > SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE) { if (s.length() > SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE) {
return obj; return obj;
......
...@@ -48,6 +48,13 @@ public class ValueStringIgnoreCase extends ValueStringBase { ...@@ -48,6 +48,13 @@ public class ValueStringIgnoreCase extends ValueStringBase {
return "CAST(" + StringUtils.quoteStringSQL(value) + " AS VARCHAR_IGNORECASE)"; return "CAST(" + StringUtils.quoteStringSQL(value) + " AS VARCHAR_IGNORECASE)";
} }
/**
* Get or create a case insensitive string value for the given string.
* The value will have the same case as the passed string.
*
* @param s the string
* @return the value
*/
public static ValueStringIgnoreCase get(String s) { public static ValueStringIgnoreCase get(String s) {
if (s.length() == 0) { if (s.length() == 0) {
return EMPTY; return EMPTY;
......
...@@ -16,9 +16,13 @@ import org.h2.util.DateTimeUtils; ...@@ -16,9 +16,13 @@ import org.h2.util.DateTimeUtils;
* Implementation of the TIME data type. * Implementation of the TIME data type.
*/ */
public class ValueTime extends Value { public class ValueTime extends Value {
public static final int PRECISION = 6; static final int PRECISION = 6;
// "10:00:00".length()
public static final int DISPLAY_SIZE = 8; /**
* The display size of the textual representation of a time.
* Example: 10:00:00
*/
static final int DISPLAY_SIZE = 8;
private final Time value; private final Time value;
...@@ -26,6 +30,12 @@ public class ValueTime extends Value { ...@@ -26,6 +30,12 @@ public class ValueTime extends Value {
this.value = value; this.value = value;
} }
/**
* Parse a string to a java.sql.Time object.
*
* @param s the string to parse
* @return the time
*/
public static Time parseTime(String s) throws SQLException { public static Time parseTime(String s) throws SQLException {
return (Time) DateTimeUtils.parseDateTime(s, Value.TIME, ErrorCode.TIME_CONSTANT_2); return (Time) DateTimeUtils.parseDateTime(s, Value.TIME, ErrorCode.TIME_CONSTANT_2);
} }
...@@ -73,11 +83,25 @@ public class ValueTime extends Value { ...@@ -73,11 +83,25 @@ public class ValueTime extends Value {
prep.setTime(parameterIndex, value); prep.setTime(parameterIndex, value);
} }
/**
* Get or create a time value for the given time.
* Clone the time.
*
* @param time the time
* @return the value
*/
public static ValueTime get(Time time) { public static ValueTime get(Time time) {
time = DateTimeUtils.cloneAndNormalizeTime(time); time = DateTimeUtils.cloneAndNormalizeTime(time);
return getNoCopy(time); return getNoCopy(time);
} }
/**
* Get or create a time value for the given time.
* Do not clone the time.
*
* @param time the time
* @return the value
*/
public static ValueTime getNoCopy(Time time) { public static ValueTime getNoCopy(Time time) {
return (ValueTime) Value.cache(new ValueTime(time)); return (ValueTime) Value.cache(new ValueTime(time));
} }
......
...@@ -21,10 +21,14 @@ import org.h2.util.MathUtils; ...@@ -21,10 +21,14 @@ import org.h2.util.MathUtils;
* Implementation of the TIMESTAMP data type. * Implementation of the TIMESTAMP data type.
*/ */
public class ValueTimestamp extends Value { public class ValueTimestamp extends Value {
public static final int PRECISION = 23; static final int PRECISION = 23;
// "2001-01-01 23:59:59.000".length()
public static final int DISPLAY_SIZE = 23; /**
public static final int DEFAULT_SCALE = 10; * The display size of the textual representation of a timestamp.
* Example: 2001-01-01 23:59:59.000
*/
static final int DISPLAY_SIZE = 23;
static final int DEFAULT_SCALE = 10;
/** /**
* This is used to find out if a date is possibly BC. Because of time zone * This is used to find out if a date is possibly BC. Because of time zone
...@@ -51,6 +55,12 @@ public class ValueTimestamp extends Value { ...@@ -51,6 +55,12 @@ public class ValueTimestamp extends Value {
return "TIMESTAMP '" + getString() + "'"; return "TIMESTAMP '" + getString() + "'";
} }
/**
* Parse a string to a java.sql.Timestamp object.
*
* @param s the string to parse
* @return the timestamp
*/
public static Timestamp parseTimestamp(String s) throws SQLException { public static Timestamp parseTimestamp(String s) throws SQLException {
return (Timestamp) DateTimeUtils.parseDateTime(s, Value.TIMESTAMP, ErrorCode.TIMESTAMP_CONSTANT_2); return (Timestamp) DateTimeUtils.parseDateTime(s, Value.TIMESTAMP, ErrorCode.TIMESTAMP_CONSTANT_2);
} }
...@@ -100,11 +110,25 @@ public class ValueTimestamp extends Value { ...@@ -100,11 +110,25 @@ public class ValueTimestamp extends Value {
prep.setTimestamp(parameterIndex, value); prep.setTimestamp(parameterIndex, value);
} }
/**
* Get or create a timestamp value for the given timestamp.
* Clone the timestamp.
*
* @param timestamp the timestamp
* @return the value
*/
public static ValueTimestamp get(Timestamp timestamp) { public static ValueTimestamp get(Timestamp timestamp) {
timestamp = (Timestamp) timestamp.clone(); timestamp = (Timestamp) timestamp.clone();
return getNoCopy(timestamp); return getNoCopy(timestamp);
} }
/**
* Get or create a timestamp value for the given timestamp.
* Do not clone the timestamp.
*
* @param timestamp the timestamp
* @return the value
*/
public static ValueTimestamp getNoCopy(Timestamp timestamp) { public static ValueTimestamp getNoCopy(Timestamp timestamp) {
return (ValueTimestamp) Value.cache(new ValueTimestamp(timestamp)); return (ValueTimestamp) Value.cache(new ValueTimestamp(timestamp));
} }
......
...@@ -17,11 +17,17 @@ import org.h2.util.StringUtils; ...@@ -17,11 +17,17 @@ import org.h2.util.StringUtils;
* Implementation of the UUID data type. * Implementation of the UUID data type.
*/ */
public class ValueUuid extends Value { public class ValueUuid extends Value {
// number of bytes
public static final int PRECISION = 16;
// cd38d882-7ada-4589-b5fb-7da0ca559d9a /**
public static final int DISPLAY_SIZE = 36; * The precision of this value in number of bytes.
*/
private static final int PRECISION = 16;
/**
* The display size of the textual representation of a UUID.
* Example: cd38d882-7ada-4589-b5fb-7da0ca559d9a
*/
private static final int DISPLAY_SIZE = 36;
private final long high, low; private final long high, low;
...@@ -34,6 +40,11 @@ public class ValueUuid extends Value { ...@@ -34,6 +40,11 @@ public class ValueUuid extends Value {
return (int) ((high >>> 32) ^ high ^ (low >>> 32) ^ low); return (int) ((high >>> 32) ^ high ^ (low >>> 32) ^ low);
} }
/**
* Create a new UUID using the pseudo random number generator.
*
* @return the new UUID
*/
public static ValueUuid getNewRandom() { public static ValueUuid getNewRandom() {
long high = RandomUtils.getSecureLong(); long high = RandomUtils.getSecureLong();
long low = RandomUtils.getSecureLong(); long low = RandomUtils.getSecureLong();
...@@ -44,6 +55,12 @@ public class ValueUuid extends Value { ...@@ -44,6 +55,12 @@ public class ValueUuid extends Value {
return new ValueUuid(high, low); return new ValueUuid(high, low);
} }
/**
* Get or create a UUID for the given 32 bytes.
*
* @param binary the byte array (must be at least 32 bytes long)
* @return the UUID
*/
public static ValueUuid get(byte[] binary) { public static ValueUuid get(byte[] binary) {
if (binary.length < 32) { if (binary.length < 32) {
return get(ByteUtils.convertBytesToString(binary)); return get(ByteUtils.convertBytesToString(binary));
...@@ -53,10 +70,23 @@ public class ValueUuid extends Value { ...@@ -53,10 +70,23 @@ public class ValueUuid extends Value {
return (ValueUuid) Value.cache(new ValueUuid(high, low)); return (ValueUuid) Value.cache(new ValueUuid(high, low));
} }
/**
* Get or create a UUID for the given high and low order values.
*
* @param high the most significant bits
* @param low the least significant bits
* @return the UUID
*/
public static ValueUuid get(long high, long low) { public static ValueUuid get(long high, long low) {
return (ValueUuid) Value.cache(new ValueUuid(high, low)); return (ValueUuid) Value.cache(new ValueUuid(high, low));
} }
/**
* Get or create a UUID for the given text representation.
*
* @param s the text representation of the UUID
* @return the UUID
*/
public static ValueUuid get(String s) { public static ValueUuid get(String s) {
long high = 0, low = 0; long high = 0, low = 0;
int i = 0; int i = 0;
...@@ -143,10 +173,20 @@ public class ValueUuid extends Value { ...@@ -143,10 +173,20 @@ public class ValueUuid extends Value {
prep.setBytes(parameterIndex, getBytes()); prep.setBytes(parameterIndex, getBytes());
} }
/**
* Get the most significant 64 bits of this UUID.
*
* @return the high order bits
*/
public long getHigh() { public long getHigh() {
return high; return high;
} }
/**
* Get the least significant 64 bits of this UUID.
*
* @return the low order bits
*/
public long getLow() { public long getLow() {
return low; return low;
} }
......
...@@ -31,6 +31,11 @@ public class ShowProgress implements DatabaseEventListener { ...@@ -31,6 +31,11 @@ public class ShowProgress implements DatabaseEventListener {
start = last = System.currentTimeMillis(); start = last = System.currentTimeMillis();
} }
/**
* This method is called when executing this sample application.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new ShowProgress().test(); new ShowProgress().test();
} }
......
...@@ -30,6 +30,11 @@ public class TestPerformance { ...@@ -30,6 +30,11 @@ public class TestPerformance {
boolean collect; boolean collect;
boolean trace; boolean trace;
/**
* This method is called when executing this sample application.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new TestPerformance().test(args); new TestPerformance().test(args);
} }
...@@ -233,7 +238,7 @@ public class TestPerformance { ...@@ -233,7 +238,7 @@ public class TestPerformance {
bench.runTest(); bench.runTest();
} }
public void trace(String s) { void trace(String s) {
if (trace) { if (trace) {
System.out.println(s); System.out.println(s);
} }
......
...@@ -50,8 +50,13 @@ public class Coverage { ...@@ -50,8 +50,13 @@ public class Coverage {
+ "-f coverage on a per-function basis\n" + "<dir> directory name (. for current directory)"); + "-f coverage on a per-function basis\n" + "<dir> directory name (. for current directory)");
} }
/**
* This method is called when executing this application.
*
* @param args the command line parameters
*/
public static void main(String[] arg) { public static void main(String[] arg) {
(new Coverage()).run(arg); new Coverage().run(arg);
} }
void run(String[] arg) { void run(String[] arg) {
......
...@@ -11,7 +11,6 @@ import java.io.FileReader; ...@@ -11,7 +11,6 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
...@@ -19,15 +18,15 @@ import java.io.Writer; ...@@ -19,15 +18,15 @@ import java.io.Writer;
* The class used at runtime to measure the code usage and performance. * The class used at runtime to measure the code usage and performance.
*/ */
public class Profile extends Thread { public class Profile extends Thread {
public static final boolean LIST_UNVISITED = false; static final boolean LIST_UNVISITED = false;
public static final boolean FAST = false; static final boolean FAST = false;
public static final boolean TRACE = false; static final boolean TRACE = false;
public static final Profile MAIN = new Profile(); static final Profile MAIN = new Profile();
public static int current; static int current;
static int top = 15; private static int top = 15;
public int[] count; int[] count;
public int[] time; int[] time;
boolean stop; boolean stop;
int maxIndex; int maxIndex;
int lastIndex; int lastIndex;
...@@ -67,6 +66,12 @@ public class Profile extends Thread { ...@@ -67,6 +66,12 @@ public class Profile extends Thread {
} }
} }
/**
* This method is called by an instrumented application whenever a line of
* code is executed.
*
* @param i the line number that is executed
*/
public static void visit(int i) { public static void visit(int i) {
if (FAST) { if (FAST) {
current = i; current = i;
...@@ -79,16 +84,16 @@ public class Profile extends Thread { ...@@ -79,16 +84,16 @@ public class Profile extends Thread {
list(); list();
} }
public static void startCollecting() { static void startCollecting() {
MAIN.stop = false; MAIN.stop = false;
MAIN.lastTime = System.currentTimeMillis(); MAIN.lastTime = System.currentTimeMillis();
} }
public static void stopCollecting() { static void stopCollecting() {
MAIN.stop = true; MAIN.stop = true;
} }
public static void list() { static void list() {
if (MAIN.lastIndex == 0) { if (MAIN.lastIndex == 0) {
// don't list anything if no statistics collected // don't list anything if no statistics collected
return; return;
...@@ -122,16 +127,6 @@ public class Profile extends Thread { ...@@ -122,16 +127,6 @@ public class Profile extends Thread {
} }
} }
public static void closeSilently(OutputStream out) {
if (out != null) {
try {
out.close();
} catch (IOException e) {
// ignore
}
}
}
void addVisit(int i) { void addVisit(int i) {
if (stop) { if (stop) {
return; return;
......
...@@ -15,8 +15,8 @@ import java.io.Reader; ...@@ -15,8 +15,8 @@ import java.io.Reader;
*/ */
public class Tokenizer { public class Tokenizer {
public static final int TYPE_EOF = -1; static final int TYPE_EOF = -1;
public static final int TYPE_WORD = -2; private static final int TYPE_WORD = -2;
private static final int TYPE_NOTHING = -3; private static final int TYPE_NOTHING = -3;
private static final byte WHITESPACE = 1; private static final byte WHITESPACE = 1;
private static final byte ALPHA = 4; private static final byte ALPHA = 4;
...@@ -49,12 +49,12 @@ public class Tokenizer { ...@@ -49,12 +49,12 @@ public class Tokenizer {
charTypes['\''] = QUOTE; charTypes['\''] = QUOTE;
} }
public Tokenizer(Reader r) { Tokenizer(Reader r) {
this(); this();
reader = r; reader = r;
} }
public String getString() { String getString() {
return value; return value;
} }
...@@ -78,20 +78,20 @@ public class Tokenizer { ...@@ -78,20 +78,20 @@ public class Tokenizer {
return i; return i;
} }
public void initToken() { void initToken() {
buffer = new StringBuffer(); buffer = new StringBuffer();
} }
public String getToken() { String getToken() {
buffer.setLength(buffer.length() - 1); buffer.setLength(buffer.length() - 1);
return buffer.toString(); return buffer.toString();
} }
private void append(int i) { void append(int i) {
buffer.append((char) i); buffer.append((char) i);
} }
public int nextToken() throws IOException { int nextToken() throws IOException {
byte[] ct = charTypes; byte[] ct = charTypes;
int c; int c;
value = null; value = null;
...@@ -262,7 +262,7 @@ public class Tokenizer { ...@@ -262,7 +262,7 @@ public class Tokenizer {
return type = c; return type = c;
} }
public int getLine() { int getLine() {
return line; return line;
} }
} }
......
...@@ -224,7 +224,7 @@ public class TestCsv extends TestBase { ...@@ -224,7 +224,7 @@ public class TestCsv extends TestBase {
conn.close(); conn.close();
} }
public void testRead() throws Exception { void testRead() throws Exception {
File f = new File(baseDir + "/test.csv"); File f = new File(baseDir + "/test.csv");
f.delete(); f.delete();
RandomAccessFile file = new RandomAccessFile(f, "rw"); RandomAccessFile file = new RandomAccessFile(f, "rw");
...@@ -268,7 +268,7 @@ public class TestCsv extends TestBase { ...@@ -268,7 +268,7 @@ public class TestCsv extends TestBase {
// 201,2,0,18 // 201,2,0,18
} }
public void testWriteRead() throws Exception { void testWriteRead() throws Exception {
deleteDb("csv"); deleteDb("csv");
......
...@@ -40,7 +40,7 @@ public class TestFunctions extends TestBase { ...@@ -40,7 +40,7 @@ public class TestFunctions extends TestBase {
testFileRead(); testFileRead();
} }
public void testFileRead() throws Exception { void testFileRead() throws Exception {
Connection conn = getConnection("functions"); Connection conn = getConnection("functions");
stat = conn.createStatement(); stat = conn.createStatement();
File f = new File(baseDir + "/test.txt"); File f = new File(baseDir + "/test.txt");
......
...@@ -45,6 +45,13 @@ public class TestScript extends TestBase { ...@@ -45,6 +45,13 @@ public class TestScript extends TestBase {
private ArrayList statements; private ArrayList statements;
private String fileName = "org/h2/test/test.in.txt"; private String fileName = "org/h2/test/test.in.txt";
/**
* Get all SQL statements of this file.
*
* @param conf the configuration
* @param file the file name
* @return the list of statements
*/
public ArrayList getAllStatements(TestAll conf, String file) throws Exception { public ArrayList getAllStatements(TestAll conf, String file) throws Exception {
config = conf; config = conf;
fileName = file; fileName = file;
...@@ -67,7 +74,7 @@ public class TestScript extends TestBase { ...@@ -67,7 +74,7 @@ public class TestScript extends TestBase {
} }
} }
public void testScript() throws Exception { void testScript() throws Exception {
deleteDb("script"); deleteDb("script");
String outFile = "test.out.txt"; String outFile = "test.out.txt";
String inFile = fileName; String inFile = fileName;
......
...@@ -65,7 +65,7 @@ public class TestSessionsLocks extends TestBase { ...@@ -65,7 +65,7 @@ public class TestSessionsLocks extends TestBase {
conn2.close(); conn2.close();
} }
public void testCancelStatement() throws Exception { void testCancelStatement() throws Exception {
deleteDb("sessionsLocks"); deleteDb("sessionsLocks");
Connection conn = getConnection("sessionsLocks;MULTI_THREADED=1"); Connection conn = getConnection("sessionsLocks;MULTI_THREADED=1");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -76,7 +76,7 @@ public class TestTransaction extends TestBase { ...@@ -76,7 +76,7 @@ public class TestTransaction extends TestBase {
c2.close(); c2.close();
} }
public void testSavepoint() throws Exception { void testSavepoint() throws Exception {
deleteDb("transaction"); deleteDb("transaction");
Connection conn = getConnection("transaction"); Connection conn = getConnection("transaction");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
...@@ -143,7 +143,7 @@ public class TestTransaction extends TestBase { ...@@ -143,7 +143,7 @@ public class TestTransaction extends TestBase {
assertEquals(count, rs.getInt(1)); assertEquals(count, rs.getInt(1));
} }
public void testIsolation() throws Exception { void testIsolation() throws Exception {
Connection conn = getConnection("transaction"); Connection conn = getConnection("transaction");
trace("default TransactionIsolation=" + conn.getTransactionIsolation()); trace("default TransactionIsolation=" + conn.getTransactionIsolation());
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
......
...@@ -149,7 +149,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -149,7 +149,7 @@ public class TestBatchUpdates extends TestBase {
conn.close(); conn.close();
} }
public void testAddBatch01() throws Exception { void testAddBatch01() throws Exception {
trace("testAddBatch01"); trace("testAddBatch01");
int i = 0; int i = 0;
int[] retValue = { 0, 0, 0 }; int[] retValue = { 0, 0, 0 };
...@@ -198,7 +198,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -198,7 +198,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testAddBatch02() throws Exception { void testAddBatch02() throws Exception {
trace("testAddBatch02"); trace("testAddBatch02");
int i = 0; int i = 0;
int[] retValue = { 0, 0, 0 }; int[] retValue = { 0, 0, 0 };
...@@ -235,7 +235,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -235,7 +235,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testClearBatch01() throws Exception { void testClearBatch01() throws Exception {
trace("testClearBatch01"); trace("testClearBatch01");
String sPrepStmt = COFFEE_UPDATE; String sPrepStmt = COFFEE_UPDATE;
trace("Prepared Statement String:" + sPrepStmt); trace("Prepared Statement String:" + sPrepStmt);
...@@ -256,7 +256,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -256,7 +256,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testClearBatch02() throws Exception { void testClearBatch02() throws Exception {
trace("testClearBatch02"); trace("testClearBatch02");
int updCountLength = 0; int updCountLength = 0;
String sUpdCoffee = COFFEE_UPDATE1; String sUpdCoffee = COFFEE_UPDATE1;
...@@ -276,7 +276,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -276,7 +276,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch01() throws Exception { void testExecuteBatch01() throws Exception {
trace("testExecuteBatch01"); trace("testExecuteBatch01");
int i = 0; int i = 0;
int[] retValue = { 0, 0, 0 }; int[] retValue = { 0, 0, 0 };
...@@ -325,7 +325,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -325,7 +325,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch02() throws Exception { void testExecuteBatch02() throws Exception {
trace("testExecuteBatch02"); trace("testExecuteBatch02");
String sPrepStmt = COFFEE_UPDATE; String sPrepStmt = COFFEE_UPDATE;
trace("Prepared Statement String:" + sPrepStmt); trace("Prepared Statement String:" + sPrepStmt);
...@@ -343,7 +343,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -343,7 +343,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch03() throws Exception { void testExecuteBatch03() throws Exception {
trace("testExecuteBatch03"); trace("testExecuteBatch03");
boolean batchExceptionFlag = false; boolean batchExceptionFlag = false;
String sPrepStmt = COFFEE_SELECT; String sPrepStmt = COFFEE_SELECT;
...@@ -364,7 +364,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -364,7 +364,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch04() throws Exception { void testExecuteBatch04() throws Exception {
trace("testExecuteBatch04"); trace("testExecuteBatch04");
int i = 0; int i = 0;
int[] retValue = { 0, 0, 0 }; int[] retValue = { 0, 0, 0 };
...@@ -400,7 +400,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -400,7 +400,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch05() throws Exception { void testExecuteBatch05() throws Exception {
trace("testExecuteBatch05"); trace("testExecuteBatch05");
int updCountLength = 0; int updCountLength = 0;
int[] updateCount = stat.executeBatch(); int[] updateCount = stat.executeBatch();
...@@ -413,7 +413,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -413,7 +413,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch06() throws Exception { void testExecuteBatch06() throws Exception {
trace("testExecuteBatch06"); trace("testExecuteBatch06");
boolean batchExceptionFlag = false; boolean batchExceptionFlag = false;
// Insert a row which is already Present // Insert a row which is already Present
...@@ -438,7 +438,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -438,7 +438,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testExecuteBatch07() throws Exception { void testExecuteBatch07() throws Exception {
trace("testExecuteBatch07"); trace("testExecuteBatch07");
boolean batchExceptionFlag = false; boolean batchExceptionFlag = false;
String selectCoffee = COFFEE_SELECT1; String selectCoffee = COFFEE_SELECT1;
...@@ -458,7 +458,7 @@ public class TestBatchUpdates extends TestBase { ...@@ -458,7 +458,7 @@ public class TestBatchUpdates extends TestBase {
} }
} }
public void testContinueBatch01() throws Exception { void testContinueBatch01() throws Exception {
trace("testContinueBatch01"); trace("testContinueBatch01");
int[] batchUpdates = { 0, 0, 0 }; int[] batchUpdates = { 0, 0, 0 };
int buCountLen = 0; int buCountLen = 0;
......
...@@ -34,7 +34,7 @@ public class TestMvcc2 extends TestBase { ...@@ -34,7 +34,7 @@ public class TestMvcc2 extends TestBase {
return getConnection("mvcc2"); return getConnection("mvcc2");
} }
public void testInsertUpdateRollback() throws Exception { void testInsertUpdateRollback() throws Exception {
Connection conn = getConnection(); Connection conn = getConnection();
conn.setAutoCommit(false); conn.setAutoCommit(false);
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
...@@ -47,7 +47,7 @@ public class TestMvcc2 extends TestBase { ...@@ -47,7 +47,7 @@ public class TestMvcc2 extends TestBase {
conn.close(); conn.close();
} }
public void testInsertRollback() throws Exception { void testInsertRollback() throws Exception {
Connection conn = getConnection(); Connection conn = getConnection();
conn.setAutoCommit(false); conn.setAutoCommit(false);
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
......
...@@ -39,7 +39,7 @@ public class FtpClient { ...@@ -39,7 +39,7 @@ public class FtpClient {
// don't allow construction // don't allow construction
} }
public static FtpClient open(String url) throws IOException { static FtpClient open(String url) throws IOException {
FtpClient client = new FtpClient(); FtpClient client = new FtpClient();
client.connect(url); client.connect(url);
return client; return client;
...@@ -77,7 +77,7 @@ public class FtpClient { ...@@ -77,7 +77,7 @@ public class FtpClient {
writer.flush(); writer.flush();
} }
public void login(String userName, String password) throws IOException { void login(String userName, String password) throws IOException {
send("USER " + userName); send("USER " + userName);
readCode(331); readCode(331);
send("PASS " + password); send("PASS " + password);
...@@ -92,7 +92,7 @@ public class FtpClient { ...@@ -92,7 +92,7 @@ public class FtpClient {
readCode(200); readCode(200);
} }
public void close() throws IOException { void close() throws IOException {
if (socket != null) { if (socket != null) {
send("QUIT"); send("QUIT");
readCode(221); readCode(221);
...@@ -100,43 +100,43 @@ public class FtpClient { ...@@ -100,43 +100,43 @@ public class FtpClient {
} }
} }
public void changeWorkingDirectory(String dir) throws IOException { void changeWorkingDirectory(String dir) throws IOException {
send("CWD " + dir); send("CWD " + dir);
readCode(250); readCode(250);
} }
public void changeDirectoryUp() throws IOException { void changeDirectoryUp() throws IOException {
send("CDUP"); send("CDUP");
readCode(250); readCode(250);
} }
public void delete(String fileName) throws IOException { void delete(String fileName) throws IOException {
send("DELE " + fileName); send("DELE " + fileName);
readCode(250); readCode(250);
} }
public void makeDirectory(String dir) throws IOException { void makeDirectory(String dir) throws IOException {
send("MKD " + dir); send("MKD " + dir);
readCode(257); readCode(257);
} }
public void mode(String mode) throws IOException { void mode(String mode) throws IOException {
send("MODE " + mode); send("MODE " + mode);
readCode(200); readCode(200);
} }
public void modificationTime(String fileName) throws IOException { void modificationTime(String fileName) throws IOException {
send("MDTM " + fileName); send("MDTM " + fileName);
readCode(213); readCode(213);
} }
public void noOperation() throws IOException { void noOperation() throws IOException {
send("NOOP"); send("NOOP");
readCode(200); readCode(200);
} }
public String printWorkingDirectory() throws IOException { String printWorkingDirectory() throws IOException {
send("PWD"); send("PWD");
readCode(257); readCode(257);
return removeQuotes(); return removeQuotes();
...@@ -177,14 +177,14 @@ public class FtpClient { ...@@ -177,14 +177,14 @@ public class FtpClient {
outData = socketData.getOutputStream(); outData = socketData.getOutputStream();
} }
public void rename(String fromFileName, String toFileName) throws IOException { void rename(String fromFileName, String toFileName) throws IOException {
send("RNFR " + fromFileName); send("RNFR " + fromFileName);
readCode(350); readCode(350);
send("RNTO " + toFileName); send("RNTO " + toFileName);
readCode(250); readCode(250);
} }
public void retrieve(String fileName, OutputStream out, long restartAt) throws IOException { void retrieve(String fileName, OutputStream out, long restartAt) throws IOException {
passive(); passive();
if (restartAt > 0) { if (restartAt > 0) {
send("REST " + restartAt); send("REST " + restartAt);
...@@ -195,19 +195,19 @@ public class FtpClient { ...@@ -195,19 +195,19 @@ public class FtpClient {
readCode(226); readCode(226);
} }
public void removeDirectory(String dir) throws IOException { void removeDirectory(String dir) throws IOException {
send("RMD " + dir); send("RMD " + dir);
readCode(250); readCode(250);
} }
public long size(String fileName) throws IOException { long size(String fileName) throws IOException {
send("SIZE " + fileName); send("SIZE " + fileName);
readCode(250); readCode(250);
long size = Long.parseLong(message); long size = Long.parseLong(message);
return size; return size;
} }
public void store(String fileName, InputStream in) throws IOException { void store(String fileName, InputStream in) throws IOException {
passive(); passive();
send("STOR " + fileName); send("STOR " + fileName);
readCode(150); readCode(150);
...@@ -215,7 +215,7 @@ public class FtpClient { ...@@ -215,7 +215,7 @@ public class FtpClient {
readCode(226); readCode(226);
} }
public String nameList(String dir) throws IOException { String nameList(String dir) throws IOException {
passive(); passive();
send("NLST " + dir); send("NLST " + dir);
readCode(150); readCode(150);
...@@ -226,7 +226,7 @@ public class FtpClient { ...@@ -226,7 +226,7 @@ public class FtpClient {
return new String(data); return new String(data);
} }
public String list(String dir) throws IOException { String list(String dir) throws IOException {
passive(); passive();
send("LIST " + dir); send("LIST " + dir);
readCode(150); readCode(150);
......
...@@ -23,7 +23,7 @@ public class TestSecurity extends TestBase { ...@@ -23,7 +23,7 @@ public class TestSecurity extends TestBase {
testXTEA(); testXTEA();
} }
public void testSHA() throws Exception { void testSHA() throws Exception {
SHA256 sha = new SHA256(); SHA256 sha = new SHA256();
testOneSHA(sha); testOneSHA(sha);
} }
...@@ -70,7 +70,7 @@ public class TestSecurity extends TestBase { ...@@ -70,7 +70,7 @@ public class TestSecurity extends TestBase {
assertEquals(expected, hash); assertEquals(expected, hash);
} }
public void testXTEA() throws Exception { void testXTEA() throws Exception {
byte[] test = new byte[4096]; byte[] test = new byte[4096];
BlockCipher xtea = CipherFactory.getBlockCipher("XTEA"); BlockCipher xtea = CipherFactory.getBlockCipher("XTEA");
xtea.setKey("abcdefghijklmnop".getBytes()); xtea.setKey("abcdefghijklmnop".getBytes());
...@@ -79,7 +79,7 @@ public class TestSecurity extends TestBase { ...@@ -79,7 +79,7 @@ public class TestSecurity extends TestBase {
} }
} }
private void testAES() throws Exception { void testAES() throws Exception {
BlockCipher test = CipherFactory.getBlockCipher("AES"); BlockCipher test = CipherFactory.getBlockCipher("AES");
test.setKey(ByteUtils.convertStringToBytes("000102030405060708090A0B0C0D0E0F")); test.setKey(ByteUtils.convertStringToBytes("000102030405060708090A0B0C0D0E0F"));
......
...@@ -103,7 +103,7 @@ public class TestTools extends TestBase { ...@@ -103,7 +103,7 @@ public class TestTools extends TestBase {
"-web", "-webPort", "9002", "-webAllowOthers", "-webSSL", "-web", "-webPort", "9002", "-webAllowOthers", "-webSSL",
"-pg", "-pgAllowOthers", "-pgPort", "9003", "-pg", "-pgAllowOthers", "-pgPort", "9003",
"-ftp", "-ftpPort", "9004", "-ftpDir", ".", "-ftpRead", "guest", "-ftpWrite", "sa", "-ftpWritePassword", "sa", "-ftpTask", "-ftp", "-ftpPort", "9004", "-ftpDir", ".", "-ftpRead", "guest", "-ftpWrite", "sa", "-ftpWritePassword", "sa", "-ftpTask",
"-tcp", "-tcpAllowOthers", "-tcpPort", "9005", "-tcpPassword", "abc"}, 0); "-tcp", "-tcpAllowOthers", "-tcpPort", "9006", "-tcpPassword", "abc"}, 0);
Server stop = server; Server stop = server;
assertTrue(result.indexOf("https://") >= 0); assertTrue(result.indexOf("https://") >= 0);
assertTrue(result.indexOf(":9002") >= 0); assertTrue(result.indexOf(":9002") >= 0);
...@@ -114,13 +114,16 @@ public class TestTools extends TestBase { ...@@ -114,13 +114,16 @@ public class TestTools extends TestBase {
assertTrue(result.indexOf("ftp://") >= 0); assertTrue(result.indexOf("ftp://") >= 0);
assertTrue(result.indexOf(":9004") >= 0); assertTrue(result.indexOf(":9004") >= 0);
assertTrue(result.indexOf("tcp://") >= 0); assertTrue(result.indexOf("tcp://") >= 0);
assertTrue(result.indexOf(":9005") >= 0); assertTrue(result.indexOf(":9006") >= 0);
result = runServer(new String[]{"-tcpShutdown", "tcp://localhost:9005", "-tcpPassword", "abc", "-tcpShutdownForce"}, 0); conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9006/mem:", "sa", "sa");
conn.close();
result = runServer(new String[]{"-tcpShutdown", "tcp://localhost:9006", "-tcpPassword", "abc", "-tcpShutdownForce"}, 0);
assertTrue(result.indexOf("Shutting down") >= 0); assertTrue(result.indexOf("Shutting down") >= 0);
stop.shutdown(); stop.shutdown();
try { try {
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9005/mem:", "sa", "sa"); conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9006/mem:", "sa", "sa");
fail(); fail();
} catch (SQLException e) { } catch (SQLException e) {
assertKnownException(e); assertKnownException(e);
......
...@@ -20,11 +20,17 @@ public class CheckJavadoc { ...@@ -20,11 +20,17 @@ public class CheckJavadoc {
private static final int MAX_COMMENT_LINE_SIZE = 80; private static final int MAX_COMMENT_LINE_SIZE = 80;
private int errorCount; private int errorCount;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new CheckJavadoc().run(); new CheckJavadoc().run();
} }
void run() throws Exception { private void run() throws Exception {
String baseDir = "src"; String baseDir = "src";
check(new File(baseDir)); check(new File(baseDir));
if (errorCount > 0) { if (errorCount > 0) {
......
...@@ -36,6 +36,12 @@ public class CheckTextFiles { ...@@ -36,6 +36,12 @@ public class CheckTextFiles {
String[] suffixIgnoreLicense = new String[] { "bat", "nsi", "txt", "properties", "xml", "java.sql.Driver", "task", "sh" }; String[] suffixIgnoreLicense = new String[] { "bat", "nsi", "txt", "properties", "xml", "java.sql.Driver", "task", "sh" };
boolean hasError; boolean hasError;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new CheckTextFiles().run(); new CheckTextFiles().run();
} }
...@@ -102,6 +108,16 @@ public class CheckTextFiles { ...@@ -102,6 +108,16 @@ public class CheckTextFiles {
} }
} }
/**
* Check a source code file. The following properties are checked:
* copyright, license, incorrect source switches, trailing white space,
* newline characters, tab characters, and characters codes (only characters
* below 128 are allowed).
*
* @param file the file to check
* @param fix automatically fix newline characters and trailing spaces
* @param checkLicense check the license and copyright
*/
public void checkOrFixFile(File file, boolean fix, boolean checkLicense) throws Exception { public void checkOrFixFile(File file, boolean fix, boolean checkLicense) throws Exception {
RandomAccessFile in = new RandomAccessFile(file, "r"); RandomAccessFile in = new RandomAccessFile(file, "r");
byte[] data = new byte[(int) file.length()]; byte[] data = new byte[(int) file.length()];
......
...@@ -21,6 +21,12 @@ public class SwitchSource { ...@@ -21,6 +21,12 @@ public class SwitchSource {
private ArrayList enable = new ArrayList(); private ArrayList enable = new ArrayList();
private ArrayList disable = new ArrayList(); private ArrayList disable = new ArrayList();
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
new SwitchSource().run(args); new SwitchSource().run(args);
} }
......
...@@ -519,4 +519,4 @@ indicate timezone unmounting beep ignoring gary tong extending respective ...@@ -519,4 +519,4 @@ indicate timezone unmounting beep ignoring gary tong extending respective
overloaded decide clash involve verification dining recursively originating overloaded decide clash involve verification dining recursively originating
philosophers technologies modeling federation enterprise semantic deductive philosophers technologies modeling federation enterprise semantic deductive
fusion legacy decoded commented trimmed reaches indicating marks scaled tells fusion legacy decoded commented trimmed reaches indicating marks scaled tells
monitor benefit performing conditional significant monitor benefit performing conditional significant arithmetic instrumented
\ No newline at end of file \ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论