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

--no commit message

--no commit message
上级 5ff0818d
......@@ -271,6 +271,9 @@ It looks like the development of this database has stopped. The last release was
</tr><tr>
<td><a href="http://mywebpage.netscape.com/davidlbarron/javaplayer.html">JavaPlayer</a></td>
<td>Pure Java MP3 player.</td>
</tr><tr>
<td><a href="http://jmatter.org/">JMatter</a></td>
<td>Framework for constructing workgroup business applications based on the Naked Objects Architectural Pattern.</td>
</tr><tr>
<td><a href="http://www.jpox.org">JPOX</a></td>
<td>Java persistent objects.</td>
......
......@@ -40,7 +40,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3>
<h3>Version 1.0.59 (2007-09-TODO)</h3><ul>
<li>A PreparedStatement that was cancelled could not be reused. Fixed.
<li>Multi-threaded kernel (MULTI_THREADED=1): A synchronization problem has been fixed.
</li><li>A PreparedStatement that was cancelled could not be reused. Fixed.
</li><li>H2 Console: Progress information when logging into a H2 embedded database (useful when opening a database is slow).
</li><li>When the database was closed while logging was disabled (LOG 0), re-opening the database was slow. Fixed.
</li><li>Fulltext search is now documented (in the Tutorial).
......@@ -782,6 +783,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>NATURAL JOIN: MySQL and PostgreSQL don't repeat columns when using SELECT * ...
</li><li>Optimize SELECT MIN(ID), MAX(ID), COUNT(*) FROM TEST WHERE ID BETWEEN 100 AND 200
</li><li>Support Oracle functions: TRUNC, NVL2, TO_CHAR, TO_DATE, TO_NUMBER
</li><li>Support setQueryTimeout (using System.currentTimeMillis in a loop; not using a thread)
</li></ul>
<h3>Not Planned</h3>
......
......@@ -111,6 +111,8 @@ The reason is, a backup of the database is created whenever the database is open
Version 10.3.1.4 was used for the test. Derby is clearly the slowest embedded database in this test.
This seems to be a structural problem, because all operations are really slow.
It will not be easy for the developers of Derby to improve the performance to a reasonable level.
A few problems have been identified: Leaving autocommit on is a problem for Derby.
If it is switched off during the whole test, the results are about 20% better for Derby.
</p>
<h4>PostgreSQL</h4>
......
......@@ -181,9 +181,7 @@ public class Database implements DataHandler {
TraceSystem.DEFAULT_TRACE_LEVEL_SYSTEM_OUT);
this.cacheType = StringUtils.toUpperEnglish(ci.removeProperty("CACHE_TYPE", CacheLRU.TYPE_NAME));
try {
synchronized (this) {
open(traceLevelFile, traceLevelSystemOut);
}
open(traceLevelFile, traceLevelSystemOut);
if (closeAtVmShutdown) {
closeOnExit = new DatabaseCloser(this, 0, true);
try {
......@@ -199,9 +197,7 @@ public class Database implements DataHandler {
traceSystem.getTrace(Trace.DATABASE).error("opening " + databaseName, e);
traceSystem.close();
}
synchronized (this) {
closeOpenFilesAndUnlock();
}
closeOpenFilesAndUnlock();
throw Message.convert(e);
}
}
......@@ -413,7 +409,7 @@ public class Database implements DataHandler {
return StringUtils.toUpperEnglish(n);
}
private void open(int traceLevelFile, int traceLevelSystemOut) throws SQLException {
private synchronized void open(int traceLevelFile, int traceLevelSystemOut) throws SQLException {
if (persistent) {
String dataFileName = databaseName + Constants.SUFFIX_DATA_FILE;
if (FileUtils.exists(dataFileName)) {
......@@ -626,7 +622,7 @@ public class Database implements DataHandler {
infoSchema.add(m);
}
private void addMeta(Session session, DbObject obj) throws SQLException {
private synchronized void addMeta(Session session, DbObject obj) throws SQLException {
if (obj.getTemporary()) {
return;
}
......@@ -642,7 +638,7 @@ public class Database implements DataHandler {
}
}
private void removeMeta(Session session, int id) throws SQLException {
private synchronized void removeMeta(Session session, int id) throws SQLException {
SearchRow r = meta.getTemplateSimpleRow(false);
r.setValue(0, ValueInt.get(id));
Cursor cursor = metaIdIndex.find(session, r, r);
......@@ -685,7 +681,7 @@ public class Database implements DataHandler {
}
}
public void addSchemaObject(Session session, SchemaObject obj) throws SQLException {
public synchronized void addSchemaObject(Session session, SchemaObject obj) throws SQLException {
obj.getSchema().add(obj);
int id = obj.getId();
if (id > 0 && !starting) {
......@@ -693,7 +689,7 @@ public class Database implements DataHandler {
}
}
public void addDatabaseObject(Session session, DbObject obj) throws SQLException {
public synchronized void addDatabaseObject(Session session, DbObject obj) throws SQLException {
HashMap map = getMap(obj.getType());
if (obj.getType() == DbObject.USER) {
User user = (User) obj;
......@@ -781,23 +777,21 @@ public class Database implements DataHandler {
}
}
void close(boolean fromShutdownHook) {
synchronized (this) {
closing = true;
if (sessions.size() > 0) {
if (!fromShutdownHook) {
return;
}
traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName + " from shutdown hook");
Session[] all = new Session[sessions.size()];
sessions.toArray(all);
for (int i = 0; i < all.length; i++) {
Session s = all[i];
try {
s.close();
} catch (SQLException e) {
traceSystem.getTrace(Trace.SESSION).error("disconnecting #" + s.getId(), e);
}
synchronized void close(boolean fromShutdownHook) {
closing = true;
if (sessions.size() > 0) {
if (!fromShutdownHook) {
return;
}
traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName + " from shutdown hook");
Session[] all = new Session[sessions.size()];
sessions.toArray(all);
for (int i = 0; i < all.length; i++) {
Session s = all[i];
try {
s.close();
} catch (SQLException e) {
traceSystem.getTrace(Trace.SESSION).error("disconnecting #" + s.getId(), e);
}
}
}
......@@ -872,7 +866,7 @@ public class Database implements DataHandler {
}
}
private void closeOpenFilesAndUnlock() throws SQLException {
private synchronized void closeOpenFilesAndUnlock() throws SQLException {
if (log != null) {
stopWriter();
log.close();
......@@ -923,7 +917,7 @@ public class Database implements DataHandler {
}
}
public int allocateObjectId(boolean needFresh, boolean dataFile) {
public synchronized int allocateObjectId(boolean needFresh, boolean dataFile) {
// TODO refactor: use hash map instead of bit field for object ids
needFresh = true;
int i;
......@@ -1008,18 +1002,18 @@ public class Database implements DataHandler {
return list;
}
public void update(Session session, DbObject obj) throws SQLException {
public synchronized void update(Session session, DbObject obj) throws SQLException {
int id = obj.getId();
removeMeta(session, id);
addMeta(session, obj);
}
public void renameSchemaObject(Session session, SchemaObject obj, String newName) throws SQLException {
public synchronized void renameSchemaObject(Session session, SchemaObject obj, String newName) throws SQLException {
obj.getSchema().rename(obj, newName);
updateWithChildren(session, obj);
}
private void updateWithChildren(Session session, DbObject obj) throws SQLException {
private synchronized void updateWithChildren(Session session, DbObject obj) throws SQLException {
ObjectArray list = obj.getChildren();
Comment comment = findComment(obj);
if (comment != null) {
......@@ -1035,7 +1029,7 @@ public class Database implements DataHandler {
}
}
public void renameDatabaseObject(Session session, DbObject obj, String newName) throws SQLException {
public synchronized void renameDatabaseObject(Session session, DbObject obj, String newName) throws SQLException {
int type = obj.getType();
HashMap map = getMap(type);
if (SysProperties.CHECK) {
......@@ -1131,7 +1125,7 @@ public class Database implements DataHandler {
return schema;
}
public void removeDatabaseObject(Session session, DbObject obj) throws SQLException {
public synchronized void removeDatabaseObject(Session session, DbObject obj) throws SQLException {
String objName = obj.getName();
int type = obj.getType();
HashMap map = getMap(type);
......@@ -1163,7 +1157,7 @@ public class Database implements DataHandler {
return null;
}
public void removeSchemaObject(Session session, SchemaObject obj) throws SQLException {
public synchronized void removeSchemaObject(Session session, SchemaObject obj) throws SQLException {
if (obj.getType() == DbObject.TABLE_OR_VIEW) {
Table table = (Table) obj;
if (table.getTemporary() && !table.getGlobalTemporary()) {
......@@ -1202,24 +1196,18 @@ public class Database implements DataHandler {
return fileIndex;
}
public void setCacheSize(int kb) throws SQLException {
public synchronized void setCacheSize(int kb) throws SQLException {
if (fileData != null) {
synchronized (fileData) {
fileData.getCache().setMaxSize(kb);
}
fileData.getCache().setMaxSize(kb);
int valueIndex = kb <= 32 ? kb : (kb >>> SysProperties.CACHE_SIZE_INDEX_SHIFT);
synchronized (fileIndex) {
fileIndex.getCache().setMaxSize(valueIndex);
}
fileIndex.getCache().setMaxSize(valueIndex);
cacheSize = kb;
}
}
public void setMasterUser(User user) throws SQLException {
synchronized (this) {
addDatabaseObject(systemSession, user);
systemSession.commit(true);
}
public synchronized void setMasterUser(User user) throws SQLException {
addDatabaseObject(systemSession, user);
systemSession.commit(true);
}
public Role getPublicRole() {
......@@ -1295,7 +1283,7 @@ public class Database implements DataHandler {
}
}
public void freeUpDiskSpace() throws SQLException {
public synchronized void freeUpDiskSpace() throws SQLException {
long sizeAvailable = 0;
if (emergencyReserve != null) {
sizeAvailable = emergencyReserve.length();
......@@ -1383,7 +1371,7 @@ public class Database implements DataHandler {
return logIndexChanges;
}
public void setLog(int level) throws SQLException {
public synchronized void setLog(int level) throws SQLException {
if (logLevel == level) {
return;
}
......@@ -1495,7 +1483,7 @@ public class Database implements DataHandler {
}
}
public void setMaxLogSize(long value) {
public synchronized void setMaxLogSize(long value) {
long minLogSize = biggestFileSize / Constants.LOG_SIZE_DIVIDER;
minLogSize = Math.max(value, minLogSize);
long currentLogSize = getLog().getMaxLogSize();
......
......@@ -70,6 +70,7 @@ public class Session implements SessionInterface {
private boolean undoLogEnabled = true;
private boolean autoCommitAtTransactionEnd;
private String currentTransactionName;
private boolean isClosed;
public Session() {
}
......@@ -109,7 +110,7 @@ public class Session implements SessionInterface {
if (!SysProperties.runFinalize) {
return;
}
if (database != null) {
if (!isClosed) {
throw Message.getInternalError("not closed", stackTrace);
}
}
......@@ -164,7 +165,7 @@ public class Session implements SessionInterface {
}
public Command prepareLocal(String sql) throws SQLException {
if (database == null) {
if (isClosed) {
throw Message.getSQLException(ErrorCode.CONNECTION_BROKEN);
}
Parser parser = new Parser(this);
......@@ -176,13 +177,11 @@ public class Session implements SessionInterface {
}
public int getPowerOffCount() {
return database == null ? 0 : database.getPowerOffCount();
return database.getPowerOffCount();
}
public void setPowerOffCount(int count) {
if (database != null) {
database.setPowerOffCount(count);
}
database.setPowerOffCount(count);
}
public void commit(boolean ddl) throws SQLException {
......@@ -277,12 +276,12 @@ public class Session implements SessionInterface {
}
public void close() throws SQLException {
if (database != null) {
if (!isClosed) {
try {
cleanTempTables(true);
database.removeSession(this);
} finally {
database = null;
isClosed = true;
}
}
}
......@@ -320,24 +319,28 @@ public class Session implements SessionInterface {
for (int i = 0; i < locks.size(); i++) {
Table t = (Table) locks.get(i);
if (!t.isLockedExclusively()) {
t.unlock(this);
locks.remove(i);
synchronized (database) {
t.unlock(this);
locks.remove(i);
}
i--;
}
}
}
private void unlockAll() throws SQLException {
if (SysProperties.CHECK) {
if (undoLog.size() > 0) {
throw Message.getInternalError();
}
}
for (int i = 0; i < locks.size(); i++) {
Table t = (Table) locks.get(i);
t.unlock(this);
synchronized (database) {
for (int i = 0; i < locks.size(); i++) {
Table t = (Table) locks.get(i);
t.unlock(this);
}
locks.clear();
}
locks.clear();
savepoints = null;
}
......@@ -368,7 +371,7 @@ public class Session implements SessionInterface {
if (traceModuleName == null) {
traceModuleName = Trace.JDBC + "[" + id + "]";
}
if (database == null) {
if (isClosed) {
return new TraceSystem(null, false).getTrace(traceModuleName);
}
return database.getTrace(traceModuleName);
......@@ -460,7 +463,7 @@ public class Session implements SessionInterface {
}
public boolean isClosed() {
return database == null;
return isClosed;
}
public void setThrottle(int throttle) {
......
......@@ -1419,6 +1419,52 @@ public class Function extends Expression implements FunctionCall {
}
public long getPrecision() {
switch (info.type) {
case ENCRYPT:
case DECRYPT:
precision = args[2].getPrecision();
break;
case COMPRESS:
precision = args[0].getPrecision();
break;
case CHAR:
precision = 1;
break;
case CONCAT:
precision = 0;
for (int i = 0; i < args.length; i++) {
precision += args[i].getPrecision();
if (precision < 0) {
precision = Long.MAX_VALUE;
}
}
break;
case HEXTORAW:
precision = (args[0].getPrecision() + 3) / 4;
break;
case LCASE:
case LTRIM:
case RIGHT:
case RTRIM:
case UCASE:
case LOWER:
case UPPER:
case TRIM:
case STRINGDECODE:
case UTF8TOSTRING:
precision = args[0].getPrecision();
break;
case RAWTOHEX:
precision = args[0].getPrecision() * 4;
break;
case SOUNDEX:
precision = 4;
break;
case DAYNAME:
case MONTHNAME:
precision = 20; // day and month names may be long in some languages
break;
}
return precision;
}
......
......@@ -188,7 +188,12 @@ public class Operation extends Expression {
public long getPrecision() {
if (right != null) {
return Math.max(left.getPrecision(), right.getPrecision());
switch (opType) {
case CONCAT:
return left.getPrecision() + right.getPrecision();
default:
return Math.max(left.getPrecision(), right.getPrecision());
}
}
return left.getPrecision();
}
......
......@@ -1237,7 +1237,7 @@ public class JdbcConnection extends TraceObject implements Connection {
int id = getNextId(TraceObject.RESULT_SET);
if (debug()) {
debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id);
debugCodeCall("executeQuery", "CALL IDENTITY()");
statement.debugCodeCallMe("executeQuery", "CALL IDENTITY()");
}
ResultSet rs = new JdbcResultSet(session, this, statement, result, id, false, true);
return rs;
......
......@@ -888,6 +888,10 @@ public class JdbcStatement extends TraceObject implements Statement {
debugCode("setPoolable("+poolable+");");
}
}
void debugCodeCallMe(String text, String param) {
debugCodeCall(text, param);
}
}
......@@ -2090,7 +2090,7 @@ If a start position is used, the characters before it are ignored.
INSTR(EMAIL,'@')
"
"Functions (String)","INSERT Function","
INSERT(originalString, startInt, lengthInt, addInt): string
INSERT(originalString, startInt, lengthInt, addString): string
","
Inserts a additional string into the original string at a specified start position.
The length specifies the number of characters that are removed at the start position
......
......@@ -90,28 +90,30 @@ public class Storage {
lastCheckedPage = file.getPage(record.getPos());
next = record.getPos() + blockCount;
}
BitField used = file.getUsed();
while (true) {
int page = file.getPage(next);
if (lastCheckedPage != page) {
if (pageIndex < 0) {
pageIndex = pages.findNextValueIndex(page);
} else {
pageIndex++;
synchronized (database) {
BitField used = file.getUsed();
while (true) {
int page = file.getPage(next);
if (lastCheckedPage != page) {
if (pageIndex < 0) {
pageIndex = pages.findNextValueIndex(page);
} else {
pageIndex++;
}
if (pageIndex >= pages.size()) {
return -1;
}
lastCheckedPage = pages.get(pageIndex);
next = Math.max(next, DiskFile.BLOCKS_PER_PAGE * lastCheckedPage);
}
if (pageIndex >= pages.size()) {
return -1;
if (used.get(next)) {
return next;
}
if (used.getLong(next) == 0) {
next = MathUtils.roundUp(next + 1, 64);
} else {
next++;
}
lastCheckedPage = pages.get(pageIndex);
next = Math.max(next, DiskFile.BLOCKS_PER_PAGE * lastCheckedPage);
}
if (used.get(next)) {
return next;
}
if (used.getLong(next) == 0) {
next = MathUtils.roundUp(next + 1, 64);
} else {
next++;
}
}
}
......@@ -153,18 +155,20 @@ public class Storage {
}
private boolean isFreeAndMine(int pos, int blocks) {
BitField used = file.getUsed();
for (int i = blocks + pos - 1; i >= pos; i--) {
if (file.getPageOwner(file.getPage(i)) != id || used.get(i)) {
return false;
synchronized (database) {
BitField used = file.getUsed();
for (int i = blocks + pos - 1; i >= pos; i--) {
if (file.getPageOwner(file.getPage(i)) != id || used.get(i)) {
return false;
}
}
return true;
}
return true;
}
public int allocate(int blockCount) throws SQLException {
if (freeList.size() > 0) {
synchronized (file) {
synchronized (database) {
BitField used = file.getUsed();
for (int i = 0; i < freeList.size(); i++) {
int px = freeList.get(i);
......
......@@ -322,12 +322,12 @@ public class TableData extends Table implements RecordReader {
return;
}
if (lockShared.isEmpty()) {
traceLock(session, exclusive, "ok");
traceLock(session, exclusive, "added for");
session.addLock(this);
lockExclusive = session;
return;
} else if (lockShared.size() == 1 && lockShared.contains(session)) {
traceLock(session, exclusive, "ok (upgrade)");
traceLock(session, exclusive, "add (upgraded) for ");
lockExclusive = session;
return;
}
......@@ -353,11 +353,11 @@ public class TableData extends Table implements RecordReader {
}
long now = System.currentTimeMillis();
if (now >= max) {
traceLock(session, exclusive, "timeout " + session.getLockTimeout());
traceLock(session, exclusive, "timeout after " + session.getLockTimeout());
throw Message.getSQLException(ErrorCode.LOCK_TIMEOUT_1, getName());
}
try {
traceLock(session, exclusive, "waiting");
traceLock(session, exclusive, "waiting for");
if (database.getLockMode() == Constants.LOCK_MODE_TABLE_GC) {
for (int i = 0; i < 20; i++) {
long free = Runtime.getRuntime().freeMemory();
......@@ -378,7 +378,7 @@ public class TableData extends Table implements RecordReader {
private void traceLock(Session session, boolean exclusive, String s) {
if (traceLock.debug()) {
traceLock.debug(session.getId() + " " + (exclusive ? "xlock" : "slock") + " " + s + " " + getName());
traceLock.debug(session.getId() + " " + (exclusive ? "exclusive write lock" : "shared read lock") + " " + s + " " + getName());
}
}
......
......@@ -4,7 +4,6 @@
*/
package org.h2.test;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
......@@ -79,6 +78,7 @@ import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock;
import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMultiThreadedKernel;
import org.h2.test.unit.TestOverflow;
import org.h2.test.unit.TestPattern;
import org.h2.test.unit.TestReader;
......@@ -147,8 +147,6 @@ java org.h2.test.TestAll timer
web page translation
TestMultiThreadedKernel and integrate in unit tests; use also in-memory and so on
At startup, when corrupted, say if LOG=0 was used before
add MVCC
......@@ -479,6 +477,7 @@ write tests using the PostgreSQL JDBC driver
new TestFileLock().runTest(this);
new TestIntArray().runTest(this);
new TestIntIntHashMap().runTest(this);
new TestMultiThreadedKernel().runTest(this);
new TestOverflow().runTest(this);
new TestPattern().runTest(this);
new TestReader().runTest(this);
......
......@@ -35,6 +35,7 @@ public class TestResultSet extends TestBase {
stat = conn.createStatement();
testColumnLength();
testArray();
testLimitMaxRows();
......@@ -57,24 +58,29 @@ public class TestResultSet extends TestBase {
}
private void testColumnLength() throws Exception {
trace("Test ColumnLength");
}
private void testLimitMaxRows() throws Exception {
trace("Test LimitMaxRows");
ResultSet rs;
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY)");
stat.execute("INSERT INTO TEST VALUES(1), (2), (3), (4)");
rs = stat.executeQuery("SELECT * FROM TEST");
checkResultRowCount(rs, 4);
rs = stat.executeQuery("SELECT * FROM TEST LIMIT 2");
checkResultRowCount(rs, 2);
stat.setMaxRows(2);
rs = stat.executeQuery("SELECT * FROM TEST");
checkResultRowCount(rs, 2);
rs = stat.executeQuery("SELECT * FROM TEST LIMIT 1");
checkResultRowCount(rs, 1);
rs = stat.executeQuery("SELECT * FROM TEST LIMIT 3");
checkResultRowCount(rs, 2);
stat.setMaxRows(0);
stat.execute("DROP TABLE TEST");
stat.execute("CREATE TABLE one (C CHARACTER(10))");
rs = stat.executeQuery("SELECT C || C FROM one;");
ResultSetMetaData md = rs.getMetaData();
check(20, md.getPrecision(1));
ResultSet rs2 = stat.executeQuery("SELECT UPPER (C) FROM one;");
ResultSetMetaData md2 = rs2.getMetaData();
check(10, md2.getPrecision(1));
rs = stat.executeQuery("SELECT UPPER (C), CHAR(10), CONCAT(C,C,C), HEXTORAW(C), RAWTOHEX(C) FROM one");
ResultSetMetaData meta = rs.getMetaData();
check(10, meta.getPrecision(1));
check(1, meta.getPrecision(2));
check(30, meta.getPrecision(3));
check(3, meta.getPrecision(4));
check(40, meta.getPrecision(5));
stat.execute("DROP TABLE one");
}
void testAutoIncrement() throws Exception {
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
public class TestMultiThreadedKernel extends TestBase implements Runnable {
private String url, user, password;
private int id;
private TestMultiThreadedKernel master;
private volatile boolean stop;
public void test() throws Exception {
if (config.networked) {
return;
}
deleteDb("multiThreadedKernel");
int count = getSize(2, 5);
Thread[] list = new Thread[count];
for (int i = 0; i < count; i++) {
TestMultiThreadedKernel r = new TestMultiThreadedKernel();
r.url = getURL("multiThreadedKernel", true);
r.user = getUser();
r.password = getPassword();
r.master = this;
r.id = i;
Thread thread = new Thread(r);
thread.setName("Thread " + i);
thread.start();
list[i] = thread;
}
Thread.sleep(getSize(2000, 5000));
stop = true;
for (int i = 0; i < count; i++) {
list[i].join();
}
SysProperties.multiThreadedKernel = false;
}
public void run() {
try {
org.h2.Driver.load();
Connection conn = DriverManager.getConnection(url + ";MULTI_THREADED=1;LOCK_MODE=3;WRITE_DELAY=0", user, password);
conn.createStatement().execute(
"CREATE TABLE TEST" + id + "(COL1 BIGINT AUTO_INCREMENT PRIMARY KEY, COL2 BIGINT)");
PreparedStatement prep = conn.prepareStatement("insert into TEST" + id + "(col2) values (?)");
for (int i = 0; !master.stop; i++) {
prep.setLong(1, i);
prep.execute();
}
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论