提交 a0f72ec6 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 b625f78f
#Mon Jan 29 22:49:09 CET 2007
benchmark.drivers.dir=D\:/data/java
#Sun Mar 04 13:24:22 CET 2007
javac=javac
benchmark.drivers.dir=D\:/data/java
version.name.maven=1.0.20070117
jdk=1.4
......@@ -15,9 +15,9 @@ Frequently Asked Questions
<h3>Are there any known bugs? When is the next release?</h3>
Usually, bugs get fixes as they are found. There is a release every few weeks.
Here is the list of known and confirmed issues as of
2007-01-30:
2007-03-04:
<ul>
<li>Can not build using ant with JDK 1.3 at the moment. However most things are fixed.
<li>Can not build using the test cases ant with JDK 1.3 at the moment. However most things are fixed.
</li><li>Some problems have been found with right outer join. Internally, it is converted to left outer join, which
does not always produce the correct results when used in combination with other joins.
</li></ul>
......
......@@ -267,7 +267,7 @@ It looks like the development of this database has stopped. The last release was
<td><a href="http://sql-workbench.net">SQL Workbench/J</a></td>
<td>Free DBMS-independent SQL Tool.</td>
</tr><tr>
<td><a href="http://squirrelsql.org">SQuirreL SQL Client</a></td>
<td><a href="http://www.squirrelsql.org">SQuirreL SQL Client</a></td>
<td>Graphical tool to view the structure of a database, browse the data, issue SQL commands etc.</td>
</tr><tr>
<td><a href="http://dbcopyplugin.sf.net">SQuirreL DB Copy Plugin</a></td>
......
......@@ -35,13 +35,28 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h2>Change Log</h2>
<h3>Version 1.0 (Current)</h3>
<h3>Version 1.0 / 2007-02-TODO</h3><ul>
<li>SCRIPT did not work correctly with BLOB or CLOB data. Fixed.
<h3>Version 1.0 / 2007-03-04</h3><ul>
<li>System sequences (automatically created sequences for IDENTITY or AUTO_INCREMENT columns) are now
random (UUIDs) to avoid clashes when merging databases using RUNSCRIPT.
</li><li>The precision for linked tables was not correct for some data types, for example VARCHAR. Fixed.
</li><li>Many problems and bugs in the XA support (package javax.sql) have been fixed.
</li><li>Now the server tool (org.h2.tools.Server) terminates with an exit code if a problem occured.
</li><li>The JDBC driver is now loaded if the JdbcDataSource class is loaded.
</li><li>After renaming a user the password becomes invalid. This is now documented.
</li><li>XAResource.recover didn't work. Fixed.
</li><li>XAResource.recover did throw an exception with the code XAER_OUTSIDE if there
was no connection. Now the code is XAER_RMERR.
</li><li>SCRIPT did not work correctly with BLOB or CLOB data. Fixed.
</li><li>BACKUP TO 'test.zip' now works with encrypted databases and CLOB and BLOB data.
</li><li>The function CASE WHEN ... didn't convert the returned value to the same data type,
resulting in unexpected behavior in many cases. Fixed.
</li><li>Truncating a table is now allowed if the table references another table
(but still not allowed if the table is references by another table).
</li><li>ORDER BY picked the wrong column if the same column name (but with a different table name)
was used twice in the select list.
</li><li>When a subquery was used in the select list of a query, and GROUP BY was used at the same time,
a NullPointerException could occur. Fixed.
</li><li>ORDER BY did not work when DISTINCT was used at the same timein some situations. Fixed.
</li><li>ORDER BY did not work when DISTINCT was used at the same time in some situations. Fixed.
</li><li>When using IN(...) on a case insensitive column (VARCHAR_IGNORECASE),
an incorrect optimization was made and the result was wrong sometimes.
</li></ul>
......@@ -1540,10 +1555,16 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>Improve command line consistency (+/- options, or true false options)
</li><li>Allow to use the catalog name in statements: [[catalog.]schema.]object
</li><li>Support curtimestamp (like curtime, curdate)
</li><li>Support ANALYZE {TABLE|INDEX} tablename COMPUTE|ESTIMATE|DELETE STATISTICS ptnOption options
</li><li>Support ANALYZE {TABLE|INDEX} tableName COMPUTE|ESTIMATE|DELETE STATISTICS ptnOption options
</li><li>Support Sequoia (Continuent.org)
</li><li>Dynamic length numbers / special methods for DataPage.writeByte / writeShort / Ronni Nielsen
</li><li>Pluggable tracing system, ThreadPool, (AvalonDB / deebee / Paul Hammant)
</li><li>Recursive Queries (see details)
</li><li>Use index on boolean flag (see details)
</li><li>Add build for embedded database only
</li><li>Release locks (shared or exclusive) on demand
</li><li>Support catalog names
</li><li>Add object id to metadata tables
</li></ul>
<h3>Not Planned</h3>
......
......@@ -3189,8 +3189,6 @@ public class Parser {
if(readIf("(")) {
String[] cols = parseColumnList(false);
command.setColumnNames(cols);
if(recursive) {
ObjectArray columns = new ObjectArray();
for(int i=0; i<cols.length; i++) {
......@@ -3200,10 +3198,7 @@ public class Parser {
recursiveTable.setTemporary(true);
session.addLocalTempTable(recursiveTable);
}
}
String select = StringCache.getNew(sqlCommand.substring(parseIndex));
read("AS");
try {
......
......@@ -72,7 +72,9 @@ public class Backup extends Prepared {
backupFile(out, fn);
db.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, name, i, max);
}
ArrayList fileList = FileLister.getDatabaseFiles(db.getDatabasePath(), name, true);
String prefix = db.getDatabasePath();
String dir = FileUtils.getParent(prefix);
ArrayList fileList = FileLister.getDatabaseFiles(dir, name, true);
for(int i=0; i<fileList.size(); i++) {
fn = (String) fileList.get(i);
if(fn.endsWith(Constants.SUFFIX_HASH_FILE) || fn.endsWith(Constants.SUFFIX_LOB_FILE)) {
......@@ -97,7 +99,7 @@ public class Backup extends Prepared {
int pos = -1;
int max = file.getReadCount();
while(true) {
pos = file.readDirect(pos, out);
pos = file.copyDirect(pos, out);
if(pos < 0) {
break;
}
......
......@@ -14,8 +14,8 @@ package org.h2.engine;
* - Run FindBugs
* - Update latest version in build.html: http://mirrors.ibiblio.org/pub/mirrors/maven2/com/h2database/h2/
* - ant jarClient, check jar file size
* - Compiling with JDK 1.3, 1.4, 1.5 and 1.6
*
* - Compile with JDK 1.3, 1.4, 1.5 and 1.6:
* set path=C:\jdk1.3.1_19\bin;%PATH%
* set JAVA_HOME=C:\jdk1.3.1_19
* ant codeswitch_jdk13
......@@ -24,19 +24,12 @@ package org.h2.engine;
* set JAVA_HOME=C:\Programme\Java\jdk1.6.0
* ant codeswitch_jdk16
* ant compile
*
* set path=C:\Programme\Java\jdk1.6.0\bin;%PATH%
* set JAVA_HOME=C:\Programme\Java\jdk1.6.0\bin
* ant codeswitch_jdk16
* ant compile
*
* ant codeswitch_jdk14
*
* - Change FAQ (next release planned, known bugs)
* - Check version, change build number in Constants.java and build.xml
* - Check code coverage
* - No " Message.getInternalError" (must be "throw Message.getInternalError")
* - space#ifdef', space#endif
* - No TODO in the docs
* - Run regression test with JDK 1.4 and 1.5
* - Change version(s) in performance.html; use latest versions of other databases
......@@ -50,8 +43,8 @@ package org.h2.engine;
* - PDF (15 min)
* - footer
* - front page
* - tables (optimal size)
* - orphan control, page breaks
* - orphan control
* - tables (optimal size), page breaks
* - table of contents
* - Switch off auto-build
* - ant all
......@@ -73,8 +66,8 @@ package org.h2.engine;
*/
public class Constants {
public static final int BUILD_ID = 42;
private static final String BUILD = "2007-02-06";
public static final int BUILD_ID = 44;
private static final String BUILD = "2007-03-04";
public static final int VERSION_MAJOR = 1;
public static final int VERSION_MINOR = 0;
......
......@@ -362,7 +362,9 @@ public class Function extends Expression implements FunctionCall {
return v0;
}
Expression result = v0.getBoolean().booleanValue() ? args[1] : args[2];
return result.getValue(session);
Value v = result.getValue(session);
v = v.convertTo(dataType);
return v;
}
case COALESCE: {
for (int i = 0; i < args.length; i++) {
......
......@@ -35,9 +35,7 @@ public class ViewIndex extends Index {
private Value[] lastParameters;
private long lastEvaluated;
private LocalResult lastResult;
private int todoRecursiveMustBePrivate;
public boolean recursive;
private boolean recursive;
private int recurseLevel;
private LocalResult recursiveResult;
......@@ -45,12 +43,9 @@ public class ViewIndex extends Index {
super(view, 0, null, null, IndexType.createNonUnique(false));
this.querySQL = querySQL;
this.originalParameters = originalParameters;
int test;
this.recursive = recursive;
columns = new Column[0];
params = new Parameter[0];
}
public String getPlanSQL() {
......@@ -244,4 +239,8 @@ public class ViewIndex extends Index {
throw Message.getUnsupportedException();
}
public void setRecursive(boolean value) {
this.recursive = value;
}
}
......@@ -52,6 +52,10 @@ Serializable, Referenceable {
private String password = "";
private String url = "";
static {
org.h2.Driver.load();
}
public JdbcDataSource() {
initFactory();
int id = getNextId(TraceObject.DATA_SOURCE);
......
......@@ -21,6 +21,7 @@ public class JdbcDataSourceFactory implements ObjectFactory {
private Trace trace;
static {
org.h2.Driver.load();
traceSystem = new TraceSystem(Constants.CLIENT_TRACE_DIRECTORY + "h2datasource" + Constants.SUFFIX_TRACE_FILE);
traceSystem.setLevelFile(TraceSystem.DEBUG);
}
......
......@@ -42,13 +42,20 @@ implements XAConnection, XAResource, JdbcConnectionListener
private JdbcConnection conn;
private ArrayList listeners = new ArrayList();
private Xid currentTransaction;
private int currentTransactionId;
private static int nextTransactionId;
JdbcXAConnection(JdbcDataSourceFactory factory, int id, String url, String user, String password) {
static {
org.h2.Driver.load();
}
JdbcXAConnection(JdbcDataSourceFactory factory, int id, String url, String user, String password) throws SQLException {
this.factory = factory;
setTrace(factory.getTrace(), TraceObject.XA_DATA_SOURCE, id);
this.url = url;
this.user = user;
this.password = password;
getConnection();
}
public XAResource getXAResource() throws SQLException {
......@@ -128,7 +135,7 @@ implements XAConnection, XAResource, JdbcConnectionListener
Statement stat = null;
try {
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.IN_DOUBT ORDER BY ID");
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.IN_DOUBT ORDER BY TRANSACTION");
ArrayList list = new ArrayList();
while(rs.next()) {
String tid = rs.getString("TRANSACTION");
......@@ -141,8 +148,8 @@ implements XAConnection, XAResource, JdbcConnectionListener
list.toArray(result);
return result;
} catch(SQLException e) {
getTrace().debug("throw XAException.XAER_OUTSIDE", e);
throw new XAException(XAException.XAER_OUTSIDE);
getTrace().debug("throw XAException.XAER_RMERR", e);
throw new XAException(XAException.XAER_RMERR);
} finally {
JdbcUtils.closeSilently(stat);
}
......@@ -151,28 +158,29 @@ implements XAConnection, XAResource, JdbcConnectionListener
private void checkOpen() throws XAException {
if(conn == null) {
getTrace().debug("conn==null");
throw new XAException(XAException.XAER_OUTSIDE);
throw new XAException(XAException.XAER_RMERR);
}
}
public int prepare(Xid xid) throws XAException {
debugCode("prepare("+quoteXid(xid)+")");
checkOpen();
if(currentTransaction != xid) {
if(!currentTransaction.equals(xid)) {
getTrace().debug("throw XAException.XAER_INVAL");
throw new XAException(XAException.XAER_INVAL);
}
Statement stat = null;
try {
stat = conn.createStatement();
stat.execute("PREPARE COMMIT");
currentTransactionId = nextTransactionId++;
stat.execute("PREPARE COMMIT TX_" + currentTransactionId);
} catch(SQLException e) {
throw convertException(e);
} finally {
JdbcUtils.closeSilently(stat);
}
getTrace().debug("return TMSUCCESS");
return TMSUCCESS;
getTrace().debug("return XA_OK");
return XA_OK;
}
public void forget(Xid xid) throws XAException {
......@@ -188,6 +196,7 @@ implements XAConnection, XAResource, JdbcConnectionListener
throw convertException(e);
}
getTrace().debug("rolled back");
currentTransaction = null;
}
public void end(Xid xid, int flags) throws XAException {
......@@ -195,12 +204,10 @@ implements XAConnection, XAResource, JdbcConnectionListener
if(flags == TMSUSPEND) {
return;
}
if(currentTransaction != xid) {
if(!currentTransaction.equals(xid)) {
getTrace().debug("throw XAException.XAER_OUTSIDE");
throw new XAException(XAException.XAER_OUTSIDE);
}
getTrace().debug("currentTransaction=null");
currentTransaction = null;
}
private String quoteFlags(int flags) {
......@@ -229,6 +236,12 @@ implements XAConnection, XAResource, JdbcConnectionListener
if((flags & XAResource.TMSUSPEND) != 0) {
buff.append("|XAResource.TMSUSPEND");
}
if ((flags & XAResource.XA_OK) != 0) {
buff.append("|XAResource.XA_OK");
}
if ((flags & XAResource.XA_RDONLY) != 0) {
buff.append("|XAResource.XA_RDONLY");
}
if(buff.length() == 0) {
buff.append("|XAResource.TMNOFLAGS");
}
......@@ -274,12 +287,21 @@ implements XAConnection, XAResource, JdbcConnectionListener
public void commit(Xid xid, boolean onePhase) throws XAException {
debugCode("commit("+quoteXid(xid)+", "+onePhase+")");
Statement stat = null;
try {
if (onePhase) {
conn.commit();
} else {
stat = conn.createStatement();
stat.execute("COMMIT TRANSACTION TX_" + currentTransactionId);
}
} catch(SQLException e) {
throw convertException(e);
} finally {
JdbcUtils.closeSilently(stat);
}
getTrace().debug("committed");
currentTransaction = null;
}
//#endif
......
......@@ -253,6 +253,7 @@ ALTER USER userName RENAME TO newUserName
","
Renames a user.
The user name is converted to uppercase if it is not quoted (with double quotes).
After renaming a user the password becomes invalid and needs to be changed as well.
Admin rights are required to execute this command.
","
ALTER USER TOM RENAME TO THOMAS
......
......@@ -125,4 +125,8 @@ public class SecureFileStore extends FileStore {
}
}
public boolean isEncrypted() {
return true;
}
}
......@@ -662,13 +662,13 @@ public class DiskFile implements CacheWriter {
}
}
public synchronized int readDirect(int pos, OutputStream out) throws SQLException {
public synchronized int copyDirect(int pos, OutputStream out) throws SQLException {
try {
if(pos < 0) {
// read the header
byte[] buffer = new byte[OFFSET];
file.seek(0);
file.readFully(buffer, 0, OFFSET);
file.readFullyDirect(buffer, 0, OFFSET);
out.write(buffer);
return 0;
}
......@@ -697,6 +697,11 @@ public class DiskFile implements CacheWriter {
if(blockCount > 1) {
file.readFully(s.getBytes(), blockSize, blockCount * blockSize - blockSize);
}
if(file.isEncrypted()) {
s.reset();
go(pos);
file.readFullyDirect(s.getBytes(), 0, blockCount * blockSize);
}
out.write(s.getBytes(), 0, blockCount * blockSize);
return pos + blockCount;
} catch (Exception e) {
......
......@@ -285,4 +285,8 @@ public class FileStore {
autoDeleteReference = null;
}
public boolean isEncrypted() {
return false;
}
}
......@@ -29,6 +29,7 @@ import org.h2.value.ValueNull;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
/**
* @author Thomas
......@@ -215,7 +216,7 @@ public class Column {
}
public void convertAutoIncrementToSequence(Session session, Schema schema, int id, boolean temporary) throws SQLException {
if(!getAutoIncrement()) {
if(!autoIncrement) {
throw Message.getInternalError();
}
if(originalSQL.equals("IDENTITY")) {
......@@ -223,7 +224,10 @@ public class Column {
}
String sequenceName;
for(int i=0; ; i++) {
sequenceName = "SYSTEM_SEQUENCE_" + i;
ValueUuid uuid = ValueUuid.getNewRandom();
String s = uuid.getString();
s = s.replace('-', '_').toUpperCase();
sequenceName = "SYSTEM_SEQUENCE_" + s;
if(schema.findSequence(sequenceName) == null) {
break;
}
......
......@@ -10,6 +10,7 @@ import java.util.HashSet;
import org.h2.api.DatabaseEventListener;
import org.h2.constraint.Constraint;
import org.h2.constraint.ConstraintReferential;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
......@@ -439,8 +440,11 @@ public class TableData extends Table implements RecordReader {
if(!(c.getConstraintType().equals(Constraint.REFERENTIAL))) {
continue;
}
ConstraintReferential ref = (ConstraintReferential) c;
if(ref.getRefTable() == this) {
return false;
}
}
return true;
}
......
......@@ -66,7 +66,6 @@ public class TableLink extends Table {
long precision = rs.getInt("COLUMN_SIZE");
int scale = rs.getInt("DECIMAL_DIGITS");
int type = DataType.convertSQLTypeToValueType(sqlType);
precision = Math.max(precision, DataType.getDataType(type).defaultPrecision);
Column col = new Column(n, type, precision, scale);
col.setTable(this, i++);
columnList.add(col);
......@@ -87,7 +86,6 @@ public class TableLink extends Table {
long precision = rsMeta.getPrecision(i+1);
int scale = rsMeta.getScale(i+1);
int type = DataType.convertSQLTypeToValueType(sqlType);
precision = Math.max(precision, DataType.getDataType(type).defaultPrecision);
Column col = new Column(n, type, precision, scale);
col.setTable(this, i++);
columnList.add(col);
......
......@@ -28,8 +28,6 @@ public class TableView extends Table {
private boolean invalid;
private Query viewQuery;
private ViewIndex index;
private int test;
private boolean recursive;
public TableView(Schema schema, int id, String name, String querySQL, ObjectArray params, String[] columnNames, Session session) throws SQLException {
......@@ -82,14 +80,13 @@ public class TableView extends Table {
cols = new Column[0];
invalid = true;
int testing;
if(columnNames != null) {
cols = new Column[columnNames.length];
for(int i=0; i<columnNames.length; i++) {
cols[i] = new Column(columnNames[i], Value.STRING, 255, 0);
}
invalid = false;
index.recursive=true;
index.setRecursive(true);
recursive = true;
}
......
......@@ -18,6 +18,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.h2.message.Message;
......@@ -195,5 +196,37 @@ public class Backup {
}
}
/**
* INTERNAL
*/
public static void restoreFiles(String zipFileName, String directory) throws IOException, SQLException {
File file = new File(zipFileName);
if(!file.exists()) {
throw new IOException("File not found: " + zipFileName);
}
FileInputStream in = null;
try {
in = new FileInputStream(file);
ZipInputStream zipIn = new ZipInputStream(in);
while(true) {
ZipEntry entry = zipIn.getNextEntry();
if(entry == null) {
break;
}
String fileName = entry.getName();
FileOutputStream out = null;
try {
out = new FileOutputStream(new File(directory, fileName));
IOUtils.copy(zipIn, out);
} finally {
IOUtils.closeSilently(out);
}
zipIn.closeEntry();
}
zipIn.closeEntry();
zipIn.close();
} finally {
IOUtils.closeSilently(in);
}
}
}
......@@ -28,6 +28,7 @@ public class Server implements Runnable {
private String name;
private Service service;
private static final int EXIT_ERROR = 1;
private void showUsage() {
System.out.println("java "+getClass().getName() + " [options]");
......@@ -69,6 +70,7 @@ public class Server implements Runnable {
* The command line interface for this tool.
* The options must be split into strings like this: "-baseDir", "/temp/data",...
* By default, -tcp, -web, -browser and -odbc are started.
* If there is a problem starting a service, the program terminates with an exit code of 1.
* The following options are supported:
* <ul>
* <li>-help or -? (print the list of options)
......@@ -105,10 +107,13 @@ public class Server implements Runnable {
* @throws SQLException
*/
public static void main(String[] args) throws SQLException {
new Server().run(args);
int exitCode = new Server().run(args);
if(exitCode != 0) {
System.exit(exitCode);
}
}
private void run(String[] args) throws SQLException {
private int run(String[] args) throws SQLException {
boolean tcpStart = false, odbcStart = false, webStart = false, ftpStart = false;
boolean browserStart = false;
boolean tcpShutdown = false, tcpShutdownForce = false;
......@@ -119,7 +124,7 @@ public class Server implements Runnable {
String a = args[i];
if(a.equals("-?") || a.equals("-help")) {
showUsage();
return;
return EXIT_ERROR;
} else if(a.equals("-web")) {
startDefaultServers = false;
webStart = true;
......@@ -145,6 +150,7 @@ public class Server implements Runnable {
browserStart = true;
}
}
int exitCode = 0;
if(startDefaultServers) {
tcpStart = true;
odbcStart = true;
......@@ -163,6 +169,7 @@ public class Server implements Runnable {
} catch(SQLException e) {
// ignore (status is displayed)
e.printStackTrace();
exitCode = EXIT_ERROR;
}
System.out.println(tcp.getStatus());
}
......@@ -173,6 +180,7 @@ public class Server implements Runnable {
} catch(SQLException e) {
// ignore (status is displayed)
e.printStackTrace();
exitCode = EXIT_ERROR;
}
System.out.println(odbc.getStatus());
}
......@@ -183,6 +191,7 @@ public class Server implements Runnable {
} catch(SQLException e) {
// ignore (status is displayed)
e.printStackTrace();
exitCode = EXIT_ERROR;
}
System.out.println(web.getStatus());
// start browser anyway (even if the server is already running)
......@@ -199,9 +208,11 @@ public class Server implements Runnable {
} catch(SQLException e) {
// ignore (status is displayed)
e.printStackTrace();
exitCode = EXIT_ERROR;
}
System.out.println(ftp.getStatus());
}
return exitCode;
}
/**
......
......@@ -55,8 +55,15 @@ public class IOUtils {
}
public static long copyAndCloseInput(InputStream in, OutputStream out) throws IOException {
long written = 0;
try {
return copy(in, out);
} finally {
in.close();
}
}
public static long copy(InputStream in, OutputStream out) throws IOException {
long written = 0;
byte[] buffer = new byte[4 * 1024];
while(true) {
int len = in.read(buffer);
......@@ -66,9 +73,6 @@ public class IOUtils {
out.write(buffer, 0, len);
written += len;
}
} finally {
in.close();
}
return written;
}
......
......@@ -9,6 +9,10 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//#ifdef JDK14
import javax.sql.XAConnection;
//#endif
public class JdbcUtils {
public static void closeSilently(Statement stat) {
......@@ -49,4 +53,16 @@ public class JdbcUtils {
return rs;
}
//#ifdef JDK14
public static void closeSilently(XAConnection conn) {
if(conn != null) {
try {
conn.close();
} catch(SQLException e) {
// ignore
}
}
}
//#endif
}
......@@ -10,6 +10,45 @@ INSERT INTO CHANNEL VALUES('H2 Database Engine' ,
CREATE TABLE ITEM(ID INT PRIMARY KEY, TITLE VARCHAR, ISSUED TIMESTAMP, DESC VARCHAR);
INSERT INTO ITEM VALUES(22,
'New version available: 1.0 / 2007-03-04', '2007-03-04 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br />
<b>Changes and new functionality:</b>
<ul>
<li>System sequences (automatically created sequences for IDENTITY or AUTO_INCREMENT columns) are now
random (UUIDs) to avoid clashes when merging databases using RUNSCRIPT.
</li><li>Now the server tool (org.h2.tools.Server) terminates with an exit code if a problem occured.
</li><li>The JDBC driver is now loaded if the JdbcDataSource class is loaded.
</li><li>After renaming a user the password becomes invalid. This is now documented.
</li><li>Truncating a table is now allowed if the table references another table
(but still not allowed if the table is references by another table).
</li>
</ul>
<b>Bugfixes:</b>
<ul>
<li>The precision for linked tables was not correct for some data types, for example VARCHAR. Fixed.
</li><li>Many problems and bugs in the XA support (package javax.sql) have been fixed.
</li><li>ORDER BY picked the wrong column if the same column name (but with a different table name)
was used twice in the select list.
</li><li>When a subquery was used in the select list of a query, and GROUP BY was used at the same time,
a NullPointerException could occur. Fixed.
</li><li>ORDER BY did not work when DISTINCT was used at the same time in some situations. Fixed.
</li><li>When using IN(...) on a case insensitive column (VARCHAR_IGNORECASE),
an incorrect optimization was made and the result was wrong sometimes.
</li><li>XAResource.recover didn''t work. Fixed.
</li><li>XAResource.recover did throw an exception with the code XAER_OUTSIDE if there
was no connection. Now the code is XAER_RMERR.
</li><li>SCRIPT did not work correctly with BLOB or CLOB data. Fixed.
</li><li>BACKUP TO ''test.zip'' now works with encrypted databases and CLOB and BLOB data.
</li><li>The function CASE WHEN ... didn''t convert the returned value to the same data type,
resulting in unexpected behavior in many cases. Fixed.
</li>
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(21,
'New version available: 1.0 / 2007-01-30', '2007-01-30 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
......@@ -546,44 +585,6 @@ For details see also the history. The plans for the next release are:
</li></ul>
');
INSERT INTO ITEM VALUES(4,
'New version available: 0.9 Beta / 2006-07-14', '2006-07-14 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br />
<b>Changes and new functionality:</b>
<ul>
<li>The cache size is now measured in blocks and no longer in rows.
Manually setting the cache size is no longer necessary in most cases.
</li><li>CREATE VIEW now supports a column list: CREATE VIEW TEST_V(A, B) AS ...
</li><li>New column IS_GENERATED in the metadata tables SEQUENCES and INDEXES.
</li><li>ResultSetMetaData.isNullable is now implemented.
</li><li>Optimization: data conversion of constants was not optimized.
</li><li>Optimization: deterministic subqueries are evaluated only once.
</li><li>Compatibility: ''T'', ''Y'', ''YES'', ''F'', ''N'', ''NO'' (case insensitive) can now also be converted to boolean.
</li><li>Compatibility: SUBSTRING(string FROM start FOR length).
</li><li>Compatibility: TRIM(whitespace FROM string).
</li><li>LIKE ... ESCAPE: The escape character may now also be an expression.
</li><li>IF EXISTS / IF NOT EXISTS implemented for the remaining CREATE / DROP statements.
</li><li>An exception was thrown if a scalar subquery returned no rows. Now NULL is returned.
</li><li>Objects of unknown type are no longer serialized to a byte array.
</li><li>Reduced jar file size: The regression tests are no longer included in the jar file.
</li></ul>
<b>Bugfixes:</b>
<ul>
<li>Issue #123: The connection to the server is lost if an abnormal exception occurs.
</li><li>Issue #124: Adding a column didn''t work when the table contains a referential integrity check.
</li><li>Issue #125: Foreign key constraints of local temporary tables are not dropped when the table is dropped.
</li><li>Issue #126: It is possible to create multiple primary keys for the same table.
</li><li>A few bugs in the CSV tool have been fixed.
</li></ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests.
</li><li>Proposal for changed license.
</li><li>For other plans, see the new ''Roadmap'' part on the web site.
</li></ul>
');
SELECT 'newsfeed-rss.xml' FILE,
XMLSTARTDOC() ||
XMLNODE('rss', XMLATTR('version', '2.0'),
......
......@@ -9,6 +9,7 @@ import java.util.Properties;
import org.h2.server.TcpServer;
import org.h2.test.jdbc.*;
import org.h2.test.jdbc.xa.TestXA;
import org.h2.test.db.*;
import org.h2.test.server.TestNestedLoop;
import org.h2.test.synth.TestBtreeIndex;
......@@ -87,107 +88,29 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
TestAll test = new TestAll();
test.printSystem();
// run TestHalt
// When you run SCRIPT DROP it drops the tables but not the autoincrement values.
// When I try to restore the db I get errors that the already exist.
// The workaround is to drop all objects at the beginning which seems to work fine.
// deebee.tar.gz
// WHERE FLAG does not use index, but WHERE FLAG=TRUE does
//
// drop table test;
// CREATE TABLE test (id int, flag BIT NOT NULL);
// CREATE INDEX idx_flag ON test(flag);
// CREATE INDEX idx_id ON test(id);
// insert into test values(1, false), (2, true), (3, false), (4, true);
// ALTER TABLE test ALTER COLUMN id SELECTIVITY 100;
// ALTER TABLE test ALTER COLUMN flag SELECTIVITY 1;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag;
//
// ALTER TABLE test ALTER COLUMN id SELECTIVITY 1;
// ALTER TABLE test ALTER COLUMN flag SELECTIVITY 100;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag;
// DROP VIEW IF EXISTS TEST_REC;
// DROP VIEW IF EXISTS TEST_2;
// DROP TABLE IF EXISTS TEST;
//
// CREATE TABLE TEST(ID INT PRIMARY KEY, PARENT INT, NAME VARCHAR(255));
// INSERT INTO TEST VALUES(1, NULL, 'Root');
// INSERT INTO TEST VALUES(2, 1, 'Plant');
// INSERT INTO TEST VALUES(3, 1, 'Animal');
// INSERT INTO TEST VALUES(4, 2, 'Tree');
// INSERT INTO TEST VALUES(5, 2, 'Flower');
// INSERT INTO TEST VALUES(6, 3, 'Elephant');
// INSERT INTO TEST VALUES(7, 3, 'Dog');
//
// CREATE FORCE VIEW TEST_2(ID, PARENT, NAME) AS SELECT ID, PARENT, NAME FROM TEST_REC;
//
// CREATE FORCE VIEW TEST_REC(ID, PARENT, NAME) AS
// SELECT ID, PARENT, NAME FROM TEST T
// WHERE PARENT IS NULL
// UNION ALL
// SELECT T.ID, T.PARENT, T.NAME
// FROM TEST T, TEST_2 R
// WHERE 1=0 AND T.PARENT=R.ID;
//
// SELECT * FROM TEST_REC;
// DROP VIEW IF EXISTS TEST_REC;
// DROP VIEW IF EXISTS TEST_2;
// DROP TABLE IF EXISTS TEST;
//
// CREATE TABLE TEST(ID INT PRIMARY KEY, PARENT INT, NAME VARCHAR(255));
// INSERT INTO TEST VALUES(1, NULL, 'Root');
// INSERT INTO TEST VALUES(2, 1, 'Plant');
// INSERT INTO TEST VALUES(3, 1, 'Animal');
// INSERT INTO TEST VALUES(4, 2, 'Tree');
// INSERT INTO TEST VALUES(5, 2, 'Flower');
// INSERT INTO TEST VALUES(6, 3, 'Elephant');
// INSERT INTO TEST VALUES(7, 3, 'Dog');
//
// CREATE VIEW RECURSIVE TEST_REC(ID, PARENT, NAME, LEVEL) AS
// SELECT ID, PARENT, NAME, 0 FROM TEST T
// WHERE PARENT IS NULL
// UNION ALL
// SELECT T.ID, T.PARENT, T.NAME, CAST(R.LEVEL AS INT)+1
// FROM TEST T, TEST_REC R
// WHERE T.PARENT=R.ID;
//
// SELECT * FROM TEST_REC;
// TODO backup : lobs are not backed up
// DROP TABLE IF EXISTS TEST;
// CREATE TABLE TEST(ID INT PRIMARY KEY, DATA CLOB);
// INSERT INTO TEST VALUES(1, space(10000));
// INSERT INTO TEST VALUES(2, 'World');
// drop table bar;
// drop table foo;
// create table FOO(id integer primary key);
// create table BAR(fooId integer);
// alter table bar add foreign key (fooid) references foo (id);
// truncate table bar;
// drop table FOO;
// create table FOO (ID int, A number(18, 2));
// insert into FOO (ID, A) values (1, 10.0), (2, 20.0);
// select SUM (CASE when ID=1 then 0 ELSE A END) col0 from Foo;
// TODO: fix Hibernate dialect bug / Bordea Felix (lost email)
// run TestHalt
// hot backup: test, test encrypted database
// BACKUP: compare sql syntax with other databases
// Hot backup (incremental backup, online backup): backup data, log, index? files
// document backup command
// WHERE FLAG does not use index, but WHERE FLAG=TRUE does
// drop table test;
// CREATE TABLE test (id int, flag BIT NOT NULL);
// CREATE INDEX idx_flag ON test(flag);
// CREATE INDEX idx_id ON test(id);
// insert into test values(1, false), (2, true), (3, false), (4, true);
// ALTER TABLE test ALTER COLUMN id SELECTIVITY 100;
// ALTER TABLE test ALTER COLUMN flag SELECTIVITY 1;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag;
//
// ALTER TABLE test ALTER COLUMN id SELECTIVITY 1;
// ALTER TABLE test ALTER COLUMN flag SELECTIVITY 100;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id between 2 and 3 AND flag=true;
// EXPLAIN SELECT * FROM test WHERE id=2 AND flag;
// h2
// update FOO set a = dateadd('second', 4320000, a);
......@@ -200,9 +123,6 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
// oracle
// update FOO set a = a + INTERVAL '4320000' SECOND;
// test backup
// backup: lobs, index
// GroovyServlet
// Cluster: hot deploy (adding a node on runtime)
......@@ -527,6 +447,7 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
new TestStatement().runTest(this);
new TestTransactionIsolation().runTest(this);
new TestUpdatableResultSet().runTest(this);
new TestXA().runTest(this);
new TestZloty().runTest(this);
afterTest();
......
......@@ -19,7 +19,7 @@ public class TestLinkedTable extends TestBase {
Connection conn = DriverManager.getConnection("jdbc:h2:"+BASE_DIR+"/linked1", "sa1", "abc");
Statement stat = conn.createStatement();
stat.execute("CREATE TEMP TABLE TEST_TEMP(ID INT PRIMARY KEY)");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), XT TINYINT, XD DECIMAL(10,2), XTS TIMESTAMP, XBY BINARY(255), XBO BIT, XSM SMALLINT, XBI BIGINT, XBL BLOB, XDA DATE, XTI TIME, XCL CLOB, XDO DOUBLE)");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(200), XT TINYINT, XD DECIMAL(10,2), XTS TIMESTAMP, XBY BINARY(255), XBO BIT, XSM SMALLINT, XBI BIGINT, XBL BLOB, XDA DATE, XTI TIME, XCL CLOB, XDO DOUBLE)");
stat.execute("CREATE INDEX IDXNAME ON TEST(NAME)");
stat.execute("INSERT INTO TEST VALUES(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello', -1, 10.30, '2001-02-03 11:22:33.4455', X'FF0102', TRUE, 3000, 1234567890123456789, X'1122AA', DATE '0002-01-01', TIME '00:00:00', 'J\u00fcrg', 2.25)");
......@@ -45,6 +45,10 @@ public class TestLinkedTable extends TestBase {
stat.execute("CREATE LINKED TABLE IF NOT EXISTS LINK_TEST('org.h2.Driver', 'jdbc:h2:"+BASE_DIR+"/linked1', 'sa1', 'abc', 'TEST')");
stat.execute("CREATE LINKED TABLE IF NOT EXISTS LINK_TEST('org.h2.Driver', 'jdbc:h2:"+BASE_DIR+"/linked1', 'sa1', 'abc', 'TEST')");
testRow(stat, "LINK_TEST");
ResultSet rs = stat.executeQuery("SELECT * FROM LINK_TEST");
ResultSetMetaData meta = rs.getMetaData();
check(10, meta.getPrecision(1));
check(200, meta.getPrecision(2));
conn.close();
conn = DriverManager.getConnection("jdbc:h2:"+BASE_DIR+"/linked2", "sa2", "def");
......@@ -52,7 +56,7 @@ public class TestLinkedTable extends TestBase {
stat.execute("INSERT INTO LINK_TEST VALUES(3, 'Link Test', 30, 100.05, '2005-12-31 12:34:56.789', X'FFEECC33', FALSE, 1, -1234567890123456789, X'4455FF', DATE '9999-12-31', TIME '23:59:59', 'George', -2.5)");
ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM LINK_TEST");
rs = stat.executeQuery("SELECT COUNT(*) FROM LINK_TEST");
rs.next();
check(rs.getInt(1), 4);
......
......@@ -8,6 +8,7 @@ import java.sql.*;
import org.h2.api.DatabaseEventListener;
import org.h2.test.TestBase;
import org.h2.tools.Backup;
public class TestOpenClose extends TestBase implements DatabaseEventListener {
......@@ -18,10 +19,38 @@ public class TestOpenClose extends TestBase implements DatabaseEventListener {
}
public void test() throws Exception {
testBackup(false);
testBackup(true);
testCase();
testReconnectFast();
}
private void testBackup(boolean encrypt) throws Exception {
deleteDb(BASE_DIR, "openClose");
String url;
if(encrypt) {
url = "jdbc:h2:"+BASE_DIR+"/openClose;CIPHER=XTEA";
} else {
url = "jdbc:h2:"+BASE_DIR+"/openClose";
}
org.h2.Driver.load();
Connection conn = DriverManager.getConnection(url, "sa", "abc def");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(C CLOB)");
stat.execute("INSERT INTO TEST VALUES(SPACE(10000))");
stat.execute("BACKUP TO '"+BASE_DIR+"/test.zip'");
conn.close();
deleteDb(BASE_DIR, "openClose");
Backup.restoreFiles(BASE_DIR + "/test.zip", BASE_DIR);
conn = DriverManager.getConnection(url, "sa", "abc def");
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
rs.next();
check(rs.getString(1).length(), 10000);
checkFalse(rs.next());
conn.close();
}
private void testReconnectFast() throws Exception {
deleteDb(BASE_DIR, "openClose");
String url = "jdbc:h2:"+BASE_DIR+"/openClose;DATABASE_EVENT_LISTENER='" + TestOpenClose.class.getName()+"'";
......
......@@ -10,6 +10,8 @@ import java.sql.Statement;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.test.TestBase;
......@@ -55,7 +57,10 @@ public class TestDataSource extends TestBase {
public void connectionErrorOccurred(ConnectionEvent event) {
}
});
XAResource res = xaConn.getXAResource();
Connection conn = xaConn.getConnection();
Xid[] list = res.recover(XAResource.TMSTARTRSCAN);
check(list.length, 0);
Statement stat = conn.createStatement();
stat.execute("SELECT * FROM DUAL");
conn.close();
......
......@@ -7,7 +7,7 @@ package org.h2.test.jdbc;
import java.sql.Connection;
import org.h2.jdbcx.JdbcDataSource;
public class TestXA {
public class TestXASimple {
int notYetImplemented;
......
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Devenish
*/
package org.h2.test.jdbc.xa;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
public class TestXA extends TestBase {
private static final String DB_NAME1 = "xadb1";
private static final String DB_NAME2 = "xadb2";
private static final String DB_URL1 = "jdbc:h2:file:" + BASE_DIR + "/" + DB_NAME1;
private static final String DB_URL2 = "jdbc:h2:file:" + BASE_DIR + "/" + DB_NAME2;
public void test() throws Exception {
deleteDb(BASE_DIR, "xa");
testXA(true);
deleteDb(BASE_DIR, DB_NAME1);
deleteDb(BASE_DIR, DB_NAME2);
testXA(false);
}
private void testXA(boolean useOneDatabase) {
XAConnection xaConn1 = null;
XAConnection xaConn2 = null;
Connection conn1 = null;
Connection conn2 = null;
Statement stat1 = null;
Statement stat2 = null;
try {
trace("xads1 = createXADatasource1()");
XADataSource xaDs1 = createXADatasource(useOneDatabase, DB_URL1);
trace("xads2 = createXADatasource2()");
XADataSource xaDs2 = createXADatasource(useOneDatabase, DB_URL2);
trace("xacon1 = xads1.getXAConnection()");
xaConn1 = xaDs1.getXAConnection();
trace("xacon2 = xads2.getXAConnection()");
xaConn2 = xaDs2.getXAConnection();
trace("xares1 = xacon1.getXAResource()");
XAResource xares1 = xaConn1.getXAResource();
trace("xares2 = xacon2.getXAResource()");
XAResource xares2 = xaConn2.getXAResource();
trace("xares1.recover(XAResource.TMSTARTRSCAN)");
Xid[] xids1 = xares1.recover(XAResource.TMSTARTRSCAN);
if ((xids1 == null) || (xids1.length == 0)) {
trace("xares1.recover(XAResource.TMSTARTRSCAN): 0");
} else {
trace("xares1.recover(XAResource.TMSTARTRSCAN): " + xids1.length);
}
trace("xares2.recover(XAResource.TMSTARTRSCAN)");
Xid[] xids2 = xares2.recover(XAResource.TMSTARTRSCAN);
if ((xids2 == null) || (xids2.length == 0)) {
trace("xares2.recover(XAResource.TMSTARTRSCAN): 0");
} else {
trace("xares2.recover(XAResource.TMSTARTRSCAN): " + xids2.length);
}
trace("con1 = xacon1.getConnection()");
conn1 = xaConn1.getConnection();
trace("stmt1 = con1.createStatement()");
stat1 = conn1.createStatement();
trace("con2 = xacon2.getConnection()");
conn2 = xaConn2.getConnection();
trace("stmt2 = con2.createStatement()");
stat2 = conn2.createStatement();
if (useOneDatabase) {
trace("stmt1.executeUpdate(\"DROP TABLE xatest1\")");
try {
stat1.executeUpdate("DROP TABLE xatest1");
} catch (SQLException e) {
}
trace("stmt2.executeUpdate(\"DROP TABLE xatest2\")");
try {
stat2.executeUpdate("DROP TABLE xatest2");
} catch (SQLException e) {
}
} else {
trace("stmt1.executeUpdate(\"DROP TABLE xatest\")");
try {
stat1.executeUpdate("DROP TABLE xatest");
} catch (SQLException e) {
}
trace("stmt2.executeUpdate(\"DROP TABLE xatest\")");
try {
stat2.executeUpdate("DROP TABLE xatest");
} catch (SQLException e) {
}
}
if (useOneDatabase) {
trace("stmt1.executeUpdate(\"CREATE TABLE xatest1 (id INT PRIMARY KEY, value INT)\")");
stat1.executeUpdate("CREATE TABLE xatest1 (id INT PRIMARY KEY, value INT)");
trace("stmt2.executeUpdate(\"CREATE TABLE xatest2 (id INT PRIMARY KEY, value INT)\")");
stat2.executeUpdate("CREATE TABLE xatest2 (id INT PRIMARY KEY, value INT)");
} else {
trace("stmt1.executeUpdate(\"CREATE TABLE xatest (id INT PRIMARY KEY, value INT)\")");
stat1.executeUpdate("CREATE TABLE xatest (id INT PRIMARY KEY, value INT)");
trace("stmt2.executeUpdate(\"CREATE TABLE xatest (id INT PRIMARY KEY, value INT)\")");
stat2.executeUpdate("CREATE TABLE xatest (id INT PRIMARY KEY, value INT)");
}
if (useOneDatabase) {
trace("stmt1.executeUpdate(\"INSERT INTO xatest1 VALUES (1, 0)\")");
stat1.executeUpdate("INSERT INTO xatest1 VALUES (1, 0)");
trace("stmt2.executeUpdate(\"INSERT INTO xatest2 VALUES (2, 0)\")");
stat2.executeUpdate("INSERT INTO xatest2 VALUES (2, 0)");
} else {
trace("stmt1.executeUpdate(\"INSERT INTO xatest VALUES (1, 0)\")");
stat1.executeUpdate("INSERT INTO xatest VALUES (1, 0)");
trace("stmt2.executeUpdate(\"INSERT INTO xatest VALUES (2, 0)\")");
stat2.executeUpdate("INSERT INTO xatest VALUES (2, 0)");
}
Xid xid1 = null;
Xid xid2 = null;
if (useOneDatabase) {
xid1 = new TestXid(1);
xid2 = new TestXid(2);
} else {
xid1 = new TestXid(1);
xid2 = xid1;
}
if (useOneDatabase) {
trace("xares1.start(xid1, XAResource.TMNOFLAGS)");
xares1.start(xid1, XAResource.TMNOFLAGS);
trace("xares2.start(xid2, XAResource.TMJOIN)");
xares2.start(xid2, XAResource.TMJOIN);
} else {
trace("xares1.start(xid1, XAResource.TMNOFLAGS)");
xares1.start(xid1, XAResource.TMNOFLAGS);
trace("xares2.start(xid2, XAResource.TMNOFLAGS)");
xares2.start(xid2, XAResource.TMNOFLAGS);
}
if (useOneDatabase) {
trace("stmt1.executeUpdate(\"UPDATE xatest1 SET value=1 WHERE id=1\")");
stat1.executeUpdate("UPDATE xatest1 SET value=1 WHERE id=1");
trace("stmt2.executeUpdate(\"UPDATE xatest2 SET value=1 WHERE id=2\")");
stat2.executeUpdate("UPDATE xatest2 SET value=1 WHERE id=2");
} else {
trace("stmt1.executeUpdate(\"UPDATE xatest SET value=1 WHERE id=1\")");
stat1.executeUpdate("UPDATE xatest SET value=1 WHERE id=1");
trace("stmt2.executeUpdate(\"UPDATE xatest SET value=1 WHERE id=2\")");
stat2.executeUpdate("UPDATE xatest SET value=1 WHERE id=2");
}
trace("xares1.end(xid1, XAResource.TMSUCCESS)");
xares1.end(xid1, XAResource.TMSUCCESS);
trace("xares2.end(xid2, XAResource.TMSUCCESS)");
xares2.end(xid2, XAResource.TMSUCCESS);
int ret1;
int ret2;
trace("ret1 = xares1.prepare(xid1)");
ret1 = xares1.prepare(xid1);
trace("xares1.prepare(xid1): " + ret1);
trace("ret2 = xares2.prepare(xid2)");
ret2 = xares2.prepare(xid2);
trace("xares2.prepare(xid2): " + ret2);
if ((ret1 != XAResource.XA_OK) && (ret1 != XAResource.XA_RDONLY)) {
throw new IllegalStateException("xares1.prepare(xid1) must return XA_OK or XA_RDONLY");
}
if ((ret2 != XAResource.XA_OK) && (ret2 != XAResource.XA_RDONLY)) {
throw new IllegalStateException("xares2.prepare(xid2) must return XA_OK or XA_RDONLY");
}
if (ret1 == XAResource.XA_OK) {
trace("xares1.commit(xid1, false)");
xares1.commit(xid1, false);
}
if (ret2 == XAResource.XA_OK) {
trace("xares2.commit(xid2, false)");
xares2.commit(xid2, false);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeSilently(stat1);
JdbcUtils.closeSilently(stat2);
JdbcUtils.closeSilently(conn1);
JdbcUtils.closeSilently(conn2);
JdbcUtils.closeSilently(xaConn1);
JdbcUtils.closeSilently(xaConn2);
}
}
private XADataSource createXADatasource(boolean useOneDatabase, String url) throws SQLException {
JdbcDataSource ds = new JdbcDataSource();
ds.setPassword("");
ds.setUser("sa");
if (useOneDatabase) {
ds.setURL(getURL("xa", true));
} else {
ds.setURL(url);
}
return ds;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Devenish
*/
package org.h2.test.jdbc.xa;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.NumberFormat;
import javax.transaction.xa.Xid;
public class TestXid implements Xid {
private static final NumberFormat NF;
private static int fXidCounter;
private int fFormatId;
private byte[] fGlobalTransactionId;
private byte[] fBranchQualifier;
private int fId;
private long fCreationTime;
static {
NumberFormat nf = NumberFormat.getIntegerInstance();
nf.setMaximumIntegerDigits(5);
nf.setMinimumIntegerDigits(5);
nf.setGroupingUsed(false);
NF = nf;
}
public static void main(String[] args) {
new TestXid();
}
public TestXid() {
this(1);
}
public TestXid(int branch) {
synchronized (TestXid.class) {
fXidCounter++;
fId = fXidCounter;
}
fCreationTime = System.currentTimeMillis();
String host;
try {
InetAddress ia = InetAddress.getLocalHost();
host = ia.getHostName();
} catch (UnknownHostException e) {
host = "localhost";
}
fFormatId = 0;
fGlobalTransactionId = new byte[MAXGTRIDSIZE];
fBranchQualifier = new byte[MAXBQUALSIZE];
StringBuffer sb;
byte[] ba;
sb = new StringBuffer();
sb.append(host);
sb.append(":");
sb.append(fId);
sb.append(":");
sb.append(fCreationTime);
// System.out.println("global transaction id: " + sb.toString());
ba = sb.toString().getBytes();
for (int i = 0; i < MAXGTRIDSIZE; i++) {
fGlobalTransactionId[i] = (byte) ' ';
}
for (int i = 0; i < ba.length; i++) {
fGlobalTransactionId[i] = ba[i];
}
sb = new StringBuffer(NF.format(branch));
// System.out.println("branch qualifier: " + sb.toString());
ba = sb.toString().getBytes();
for (int i = 0; i < MAXBQUALSIZE; i++) {
fBranchQualifier[i] = (byte) ' ';
}
for (int i = 0; i < ba.length; i++) {
fBranchQualifier[i] = ba[i];
}
}
public int getFormatId() {
return fFormatId;
}
public byte[] getGlobalTransactionId() {
return fGlobalTransactionId;
}
public byte[] getBranchQualifier() {
return fBranchQualifier;
}
}
--- special grammar and test cases ---------------------------------------------------------------------------------------------
create table FOO(id integer primary key);
> ok
create table BAR(fooId integer);
> ok
alter table bar add foreign key (fooId) references foo (id);
> ok
truncate table bar;
> ok
truncate table foo;
> exception
drop table bar, foo;
> ok
CREATE TABLE TESTA(ID IDENTITY);
> ok
......@@ -476,19 +494,16 @@ create domain email as varchar(200) check (position('@' in value) > 1);
create domain gmail as email default '@gmail.com' check (position('gmail' in value) > 1);
> ok
create memory table address(id identity, name email, name2 gmail);
create memory table address(id int primary key, name email, name2 gmail);
> ok
insert into address(name, name2) values('test@abc', 'test@gmail.com');
insert into address(id, name, name2) values(1, 'test@abc', 'test@gmail.com');
> update count: 1
insert into address(name, name2) values('test@abc', 'test@acme');
> exception
insert into address(name, name2) values('test_abc', 'test@gmail');
insert into address(id, name, name2) values(2, 'test@abc', 'test@acme');
> exception
insert into address2(name) values('test_abc'), (null);
insert into address(id, name, name2) values(3, 'test_abc', 'test@gmail');
> exception
insert into address2(name) values('test@abc');
......@@ -538,7 +553,7 @@ select * from information_schema.domains;
script nodata nopasswords nosettings;
> SCRIPT
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -- 1 = SELECT COUNT(*) FROM PUBLIC.ADDRESS
> -- 1 = SELECT COUNT(*) FROM PUBLIC.TEST
> CREATE DOMAIN EMAIL AS VARCHAR(200) CHECK (POSITION('@', VALUE) > 1)
......@@ -548,12 +563,11 @@ script nodata nopasswords nosettings;
> CREATE DOMAIN STRING2 AS VARCHAR NOT NULL
> CREATE DOMAIN STRING3 AS VARCHAR DEFAULT '<empty>'
> CREATE DOMAIN STRING_X AS VARCHAR DEFAULT '<empty>'
> CREATE MEMORY TABLE PUBLIC.ADDRESS( ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, NAME VARCHAR(200) CHECK (POSITION('@', NAME) > 1), NAME2 VARCHAR(200) DEFAULT '@gmail.com' CHECK ((POSITION('@', NAME2) > 1) AND (POSITION('gmail', NAME2) > 1)) )
> CREATE MEMORY TABLE PUBLIC.ADDRESS( ID INT NOT NULL, NAME VARCHAR(200) CHECK (POSITION('@', NAME) > 1), NAME2 VARCHAR(200) DEFAULT '@gmail.com' CHECK ((POSITION('@', NAME2) > 1) AND (POSITION('gmail', NAME2) > 1)) )
> CREATE MEMORY TABLE PUBLIC.TEST( A VARCHAR(255) DEFAULT '', B VARCHAR, C VARCHAR, D VARCHAR DEFAULT '<empty>' )
> CREATE PRIMARY KEY ON PUBLIC.ADDRESS(ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 4 BELONGS_TO_TABLE
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> rows: 14
> rows: 13
drop table test;
> ok
......@@ -1448,7 +1462,7 @@ call (select x from dual where x is null);
create sequence test_seq;
> ok
create table test(id identity, parent int);
create table test(id int primary key, parent int);
> ok
create index ni on test(parent);
......@@ -1470,10 +1484,9 @@ select * from INFORMATION_SCHEMA.INDEXES;
select * from INFORMATION_SCHEMA.SEQUENCES;
> SEQUENCE_CATALOG SEQUENCE_SCHEMA SEQUENCE_NAME CURRENT_VALUE INCREMENT IS_GENERATED REMARKS
> ---------------- --------------- ----------------- ------------- --------- ------------ -------
> SCRIPT PUBLIC SYSTEM_SEQUENCE_0 0 1 TRUE
> ---------------- --------------- ------------- ------------- --------- ------------ -------
> SCRIPT PUBLIC TEST_SEQ 0 1 FALSE
> rows: 2
> rows: 1
drop table test;
> ok
......@@ -2274,7 +2287,7 @@ drop table test;
> ok
--- script drop ---------------------------------------------------------------------------------------------
create memory table test (id int auto_increment, im_ie varchar(10));
create memory table test (id int primary key, im_ie varchar(10));
> ok
create sequence test_seq;
......@@ -2282,16 +2295,15 @@ create sequence test_seq;
script NODATA NOPASSWORDS NOSETTINGS drop;
> SCRIPT
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -----------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM PUBLIC.TEST
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, IM_IE VARCHAR(10) )
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT NOT NULL, IM_IE VARCHAR(10) )
> CREATE PRIMARY KEY ON PUBLIC.TEST(ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 1 BELONGS_TO_TABLE
> CREATE SEQUENCE PUBLIC.TEST_SEQ START WITH 1
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> DROP SEQUENCE IF EXISTS PUBLIC.TEST_SEQ
> DROP TABLE IF EXISTS PUBLIC.TEST
> rows: 8
> rows: 7
drop sequence test_seq;
> ok
......@@ -2493,7 +2505,7 @@ CREATE TABLE CHILD(PARENTID INT, FOREIGN KEY(PARENTID) REFERENCES PARENT(ID), NA
> ok
TRUNCATE TABLE CHILD;
> exception
> ok
TRUNCATE TABLE PARENT;
> exception
......@@ -2957,7 +2969,7 @@ DROP TABLE IF EXISTS TEST;
> ok
--- script ---------------------------------------------------------------------------------------------
create memory table test(id identity, c clob, b blob);
create memory table test(id int primary key, c clob, b blob);
> ok
insert into test values(0, null, null);
......@@ -2971,16 +2983,15 @@ insert into test values(2, 'Cafe', X'cafe');
script nopasswords nosettings;
> SCRIPT
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> ------------------------------------------------------------------------------
> -- 3 = SELECT COUNT(*) FROM PUBLIC.TEST
> CREATE MEMORY TABLE PUBLIC.TEST( ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, C CLOB, B BLOB )
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT NOT NULL, C CLOB, B BLOB )
> CREATE PRIMARY KEY ON PUBLIC.TEST(ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 3 BELONGS_TO_TABLE
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> INSERT INTO PUBLIC.TEST(ID, C, B) VALUES(0, NULL, NULL)
> INSERT INTO PUBLIC.TEST(ID, C, B) VALUES(1, '', X'')
> INSERT INTO PUBLIC.TEST(ID, C, B) VALUES(2, 'Cafe', X'cafe')
> rows: 8
> rows: 7
drop table test;
> ok
......@@ -3579,20 +3590,19 @@ DROP TABLE TEST;
> ok
--- autoIncrement ----------------------------------------------------------------------------------------------
CREATE MEMORY TABLE TEST(ID IDENTITY PRIMARY KEY, NAME VARCHAR);
CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR);
> ok
SCRIPT NOPASSWORDS NOSETTINGS;
> SCRIPT
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> ------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM PUBLIC.TEST
> CREATE MEMORY TABLE PUBLIC.TEST( ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, NAME VARCHAR )
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT NOT NULL, NAME VARCHAR )
> CREATE PRIMARY KEY ON PUBLIC.TEST(ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 1 BELONGS_TO_TABLE
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> rows: 5
> rows: 4
INSERT INTO TEST(NAME) VALUES('Hi'), ('World');
INSERT INTO TEST(ID, NAME) VALUES(1, 'Hi'), (2, 'World');
> update count: 2
SELECT * FROM TEST;
......@@ -7541,28 +7551,21 @@ create memory table word(word_id integer, name varchar);
alter table word alter column word_id integer(10) auto_increment;
> ok
script NOPASSWORDS NOSETTINGS;
> SCRIPT
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM PUBLIC.WORD
> CREATE MEMORY TABLE PUBLIC.WORD( WORD_ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, NAME VARCHAR )
> CREATE PRIMARY KEY ON PUBLIC.WORD(WORD_ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 1 BELONGS_TO_TABLE
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> rows: 5
insert into word(name) values('Hello');
> update count: 1
alter table word alter column word_id restart with 30872;
> ok
script NOPASSWORDS NOSETTINGS;
> SCRIPT
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -- 0 = SELECT COUNT(*) FROM PUBLIC.WORD
> CREATE MEMORY TABLE PUBLIC.WORD( WORD_ID BIGINT DEFAULT (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_0) NOT NULL NULL_TO_DEFAULT SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0, NAME VARCHAR )
> CREATE PRIMARY KEY ON PUBLIC.WORD(WORD_ID)
> CREATE SEQUENCE PUBLIC.SYSTEM_SEQUENCE_0 START WITH 30872 BELONGS_TO_TABLE
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN
> rows: 5
insert into word(name) values('World');
> update count: 1
select * from word;
> WORD_ID NAME
> ------- -----
> 1 Hello
> 30872 World
> rows: 2
drop table word;
> ok
......
create table FOO (ID int, A number(18, 2));
insert into FOO (ID, A) values (1, 10.0), (2, 20.0);
select SUM (CASE when ID=1 then 0 ELSE A END) col0 from Foo;
> 20.00;
drop table FOO;
select (SELECT true)+1 GROUP BY 1;
> 2;
create table FOO (ID int, A number(18, 2));
......
......@@ -441,5 +441,12 @@ yyyy zeile zero zeros zeta zip zloty zone zwj zwnj
unavailable repeating sponsored indonesian yuliantoro joko indonesia unlike
truncating ronni ptn avalon nielsen hammant picked sequoia continuent deebee paul
lister testa testb tar von
### check those again:
populate slowly xacon inser maxbqualsize counter regards attaching official xatest xids rmerr xadb rdonly occured maxgtridsize bordea con patches suffixer risky
### evaluatable > evaluable
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论