提交 7dc21ec5 authored 作者: Thomas Mueller's avatar Thomas Mueller

Fulltext search: there was a memory leak when creating and dropping fulltext indexes in a loop.

上级 739e2a0d
......@@ -8,6 +8,7 @@ package org.h2.fulltext;
import java.io.IOException;
import java.io.Reader;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
......@@ -22,6 +23,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.h2.api.CloseListener;
import org.h2.api.Trigger;
import org.h2.command.Parser;
import org.h2.engine.Session;
......@@ -43,7 +45,7 @@ import org.h2.value.DataType;
/**
* This class implements the native full text search.
*/
public class FullText implements Trigger {
public class FullText implements Trigger, CloseListener {
private static final String TRIGGER_PREFIX = "FT_";
private static final String SCHEMA = "FT";
......@@ -73,6 +75,7 @@ public class FullText implements Trigger {
*/
private static final String FIELD_KEYS = "KEYS";
private FullTextSettings setting;
private IndexInfo index;
private int[] dataTypes;
private PreparedStatement prepInsertWord, prepInsertRow, prepInsertMap;
......@@ -260,6 +263,7 @@ public class FullText implements Trigger {
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA);
removeAllTriggers(conn);
FullTextSettings setting = FullTextSettings.getInstance(conn);
setting.removeAllIndexes();
setting.getIgnoreList().clear();
setting.getWordList().clear();
}
......@@ -327,7 +331,7 @@ public class FullText implements Trigger {
*/
public void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before, int type) throws SQLException {
init(conn);
FullTextSettings setting = FullTextSettings.getInstance(conn);
setting = FullTextSettings.getInstance(conn);
ArrayList keyList = new ArrayList();
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs = meta.getColumns(null, schemaName, tableName, null);
......@@ -420,7 +424,6 @@ public class FullText implements Trigger {
* INTERNAL
*/
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
FullTextSettings setting = FullTextSettings.getInstance(conn);
if (oldRow != null) {
delete(setting, oldRow);
}
......@@ -470,7 +473,7 @@ public class FullText implements Trigger {
return "'" + ByteUtils.convertBytesToString(data) + "'";
}
private String asString(Object data, int type) throws SQLException {
static String asString(Object data, int type) throws SQLException {
if (data == null) {
return "NULL";
}
......@@ -495,6 +498,9 @@ public class FullText implements Trigger {
return data.toString();
case Types.CLOB:
try {
if (data instanceof Clob) {
data = ((Clob) data).getCharacterStream();
}
return IOUtils.readStringAndClose((Reader) data, -1);
} catch (IOException e) {
throw Message.convert(e);
......@@ -825,4 +831,12 @@ public class FullText implements Trigger {
}
}
public void close() throws SQLException {
setting.removeIndexInfo(index);
}
public void remove() throws SQLException {
setting.removeIndexInfo(index);
}
}
......@@ -8,7 +8,6 @@ package org.h2.fulltext;
//## Java 1.4 begin ##
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
......@@ -38,11 +37,9 @@ import org.h2.command.Parser;
import org.h2.engine.Session;
import org.h2.expression.ExpressionColumn;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.Message;
import org.h2.store.fs.FileSystem;
import org.h2.tools.SimpleResultSet;
import org.h2.util.ByteUtils;
import org.h2.util.IOUtils;
import org.h2.util.StringUtils;
//## Java 1.4 end ##
......@@ -413,53 +410,6 @@ implements Trigger, CloseListener
return "'" + ByteUtils.convertBytesToString(data) + "'";
}
private String asString(Object data, int type) throws SQLException {
if (data == null) {
return "NULL";
}
switch (type) {
case Types.BIT:
case Types.BOOLEAN:
case Types.INTEGER:
case Types.BIGINT:
case Types.DECIMAL:
case Types.DOUBLE:
case Types.FLOAT:
case Types.NUMERIC:
case Types.REAL:
case Types.SMALLINT:
case Types.TINYINT:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.LONGVARCHAR:
case Types.CHAR:
case Types.VARCHAR:
return data.toString();
case Types.CLOB:
try {
return IOUtils.readStringAndClose((Reader) data, -1);
} catch (IOException e) {
throw Message.convert(e);
}
case Types.VARBINARY:
case Types.LONGVARBINARY:
case Types.BINARY:
case Types.JAVA_OBJECT:
case Types.OTHER:
case Types.BLOB:
case Types.STRUCT:
case Types.REF:
case Types.NULL:
case Types.ARRAY:
case Types.DATALINK:
case Types.DISTINCT:
throw new SQLException("FULLTEXT", "Unsupported column data type: " + type);
default:
return "";
}
}
private String quoteSQL(Object data, int type) throws SQLException {
if (data == null) {
return "NULL";
......@@ -635,6 +585,10 @@ implements Trigger, CloseListener
throw convertException(e);
}
}
public void remove() throws SQLException {
// ignore
}
//## Java 1.4 end ##
}
......@@ -120,4 +120,12 @@ class FullTextSettings {
this.prepSelectRowById = prepSelectRowById;
}
void removeAllIndexes() {
indexes.clear();
}
public void removeIndexInfo(IndexInfo index) {
indexes.remove(ObjectUtils.getLong(index.id));
}
}
......@@ -13,6 +13,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.StringTokenizer;
import org.h2.fulltext.FullText;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
......@@ -21,7 +22,17 @@ import org.h2.test.TestBase;
*/
public class TestFullText extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String[] a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws SQLException {
testCreateDrop();
if (config.memory) {
return;
}
......@@ -46,6 +57,22 @@ public class TestFullText extends TestBase {
}
private void testCreateDrop() throws SQLException {
deleteDb("fullText");
FileSystem.getInstance(baseDir).deleteRecursive(baseDir + "/fullText");
Connection conn = getConnection("fullText");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS IF NOT EXISTS FT_INIT FOR \"org.h2.fulltext.FullText.init\"");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
for (int i = 0; i < 10; i++) {
FullText.createIndex(conn, "PUBLIC", "TEST", null);
FullText.dropIndex(conn, "PUBLIC", "TEST");
}
conn.close();
deleteDb("fullText");
FileSystem.getInstance(baseDir).deleteRecursive(baseDir + "/fullText");
}
private void testReopen(boolean lucene) throws SQLException {
String prefix = lucene ? "FTL" : "FT";
deleteDb("fullTextReopen");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论