提交 2a83a1ba authored 作者: Thomas Mueller's avatar Thomas Mueller

the lucene index was always recreated and never closed

上级 4ba52d30
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.api;
import java.sql.SQLException;
/**
* A trigger that implements this interface will be notified when the database
* is closed.
*/
public interface CloseListener {
/**
* This method is called when the database is closed.
* If the method throws an exception, it will be logged, but
* closing the database will continue.
*
* @throws SQLException
*/
void close() throws SQLException;
}
......@@ -34,6 +34,7 @@ import org.h2.result.SearchRow;
import org.h2.schema.Schema;
import org.h2.schema.SchemaObject;
import org.h2.schema.Sequence;
import org.h2.schema.TriggerObject;
import org.h2.store.DataHandler;
import org.h2.store.DataPage;
import org.h2.store.DiskFile;
......@@ -1043,6 +1044,11 @@ public class Database implements DataHandler {
Sequence sequence = (Sequence) sequences.get(i);
sequence.close();
}
ObjectArray triggers = getAllSchemaObjects(DbObject.TRIGGER);
for (int i = 0; i < triggers.size(); i++) {
TriggerObject trigger = (TriggerObject) triggers.get(i);
trigger.close();
}
meta.close(systemSession);
systemSession.commit(true);
indexSummaryValid = true;
......
......@@ -18,21 +18,22 @@ import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.table.Table;
import org.h2.util.ClassUtils;
import org.h2.util.ObjectArray;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueNull;
/**
* Represents a user-defined function, or alias.
*
* @author Thomas Mueller
* @author Gary Tong
*/
public class FunctionAlias extends DbObjectBase {
private boolean hasConnectionParam;
private String className;
private String methodName;
private Method javaMethod;
private int paramCount;
private int dataType;
private JavaMethod[] javaMethods;
public FunctionAlias(Database db, int id, String name, String javaClassMethod, boolean force) throws SQLException {
initDbObjectBase(db, id, name, Trace.FUNCTION);
......@@ -55,38 +56,38 @@ public class FunctionAlias extends DbObjectBase {
}
private synchronized void load() throws SQLException {
if (javaMethod != null) {
if (javaMethods != null) {
return;
}
Class javaClass = ClassUtils.loadUserClass(className);
Method[] methods = javaClass.getMethods();
ObjectArray list = new ObjectArray();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (!Modifier.isStatic(m.getModifiers())) {
continue;
}
if (m.getName().equals(methodName)) {
javaMethod = m;
break;
} else if (getMethodSignature(m).equals(methodName)) {
javaMethod = m;
break;
if (m.getName().equals(methodName) || getMethodSignature(m).equals(methodName)) {
JavaMethod javaMethod = new JavaMethod(m);
for (int j = 0; j < list.size(); j++) {
JavaMethod old = (JavaMethod) list.get(j);
if (old.paramCount == javaMethod.paramCount) {
throw Message.getSQLException(ErrorCode.METHODS_MUST_HAVE_DIFFERENT_PARAMETER_COUNTS_2,
new String[] {
old.method.toString(),
javaMethod.method.toString()
}
);
}
if (javaMethod == null) {
throw Message.getSQLException(ErrorCode.METHOD_NOT_FOUND_1, methodName + " (" + className + ")");
}
Class[] paramClasses = javaMethod.getParameterTypes();
paramCount = paramClasses.length;
if (paramCount > 0) {
Class paramClass = paramClasses[0];
if (Connection.class.isAssignableFrom(paramClass)) {
hasConnectionParam = true;
paramCount--;
list.add(javaMethod);
}
}
Class returnClass = javaMethod.getReturnType();
dataType = DataType.getTypeFromClass(returnClass);
if (list.size() == 0) {
throw Message.getSQLException(ErrorCode.METHOD_NOT_FOUND_1, methodName + " (" + className + ")");
}
javaMethods = new JavaMethod[list.size()];
list.toArray(javaMethods);
}
private String getMethodSignature(Method m) {
......@@ -110,15 +111,6 @@ public class FunctionAlias extends DbObjectBase {
return buff.toString();
}
public Class[] getColumnClasses() throws SQLException {
load();
return javaMethod.getParameterTypes();
}
public int getDataType() {
return dataType;
}
public String getCreateSQLForCopy(Table table, String quotedName) {
throw Message.getInternalError();
}
......@@ -144,7 +136,7 @@ public class FunctionAlias extends DbObjectBase {
database.removeMeta(session, getId());
className = null;
methodName = null;
javaMethod = null;
javaMethods = null;
invalidate();
}
......@@ -152,6 +144,76 @@ public class FunctionAlias extends DbObjectBase {
throw Message.getUnsupportedException();
}
/**
* Find the Java method that matches the arguments.
*
* @param args the argument list
* @return the Java method
* @throws SQLException if no matching method could be found
*/
public JavaMethod findJavaMethod(Expression[] args) throws SQLException {
load();
for (int i = 0; i < javaMethods.length; i++) {
if (javaMethods[i].paramCount == args.length) {
return javaMethods[i];
}
}
throw Message.getSQLException(ErrorCode.METHOD_NOT_FOUND_1, methodName + " (" + className + ")");
}
public String getJavaClassName() {
return this.className;
}
public String getJavaMethodName() {
return this.methodName;
}
/**
* Get the Java methods mapped by this function.
*
* @return the Java methods.
*/
public JavaMethod[] getJavaMethods() throws SQLException {
load();
return javaMethods;
}
/**
* There may be multiple Java methods that match a function name.
* Each method must have a different number of parameters however.
* This helper class represents one such method.
*/
public static class JavaMethod {
Method method;
boolean hasConnectionParam;
int paramCount;
int dataType;
JavaMethod(Method method) throws SQLException {
this.method = method;
Class[] paramClasses = method.getParameterTypes();
paramCount = paramClasses.length;
if (paramCount > 0) {
Class paramClass = paramClasses[0];
if (Connection.class.isAssignableFrom(paramClass)) {
hasConnectionParam = true;
paramCount--;
}
}
Class returnClass = method.getReturnType();
dataType = DataType.getTypeFromClass(returnClass);
}
/**
* Check if this function requires a database connection.
*
* @return if the function requires a connection
*/
public boolean hasConnectionParam() {
return this.hasConnectionParam;
}
/**
* Call the user-defined function and return the value.
*
......@@ -160,9 +222,8 @@ public class FunctionAlias extends DbObjectBase {
* @param columnList true if the function should only return the column list
* @return the value
*/
public synchronized Value getValue(Session session, Expression[] args, boolean columnList) throws SQLException {
load();
Class[] paramClasses = javaMethod.getParameterTypes();
public Value getValue(Session session, Expression[] args, boolean columnList) throws SQLException {
Class[] paramClasses = method.getParameterTypes();
Object[] params = new Object[paramClasses.length];
int p = 0;
if (hasConnectionParam && params.length > 0) {
......@@ -199,7 +260,7 @@ public class FunctionAlias extends DbObjectBase {
session.setAutoCommit(false);
try {
Object returnValue;
returnValue = javaMethod.invoke(null, params);
returnValue = method.invoke(null, params);
if (returnValue == null) {
return ValueNull.INSTANCE;
}
......@@ -213,26 +274,18 @@ public class FunctionAlias extends DbObjectBase {
}
}
public int getParameterCount() throws SQLException {
load();
return paramCount;
public Class[] getColumnClasses() throws SQLException {
return method.getParameterTypes();
}
public String getJavaClassName() {
return this.className;
public int getDataType() {
return dataType;
}
public String getJavaMethodName() {
return this.methodName;
public int getParameterCount() throws SQLException {
return paramCount;
}
/**
* Check if this function requires a database connection.
*
* @return if the function requires a connection
*/
public boolean hasConnectionParam() {
return this.hasConnectionParam;
}
}
......@@ -32,6 +32,7 @@ import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.h2.api.CloseListener;
import org.h2.api.Trigger;
import org.h2.command.Parser;
import org.h2.engine.Session;
......@@ -50,7 +51,7 @@ import org.h2.util.StringUtils;
*/
public class FullTextLucene extends FullText
//## Java 1.4 begin ##
implements Trigger
implements Trigger, CloseListener
//## Java 1.4 end ##
{
......@@ -574,8 +575,9 @@ implements Trigger
synchronized (indexers) {
indexer = (IndexModifier) indexers.get(path);
if (indexer == null) {
// TODO: create flag = true means re-create
indexer = new IndexModifier(path, new StandardAnalyzer(), true);
Analyzer analyzer = new StandardAnalyzer();
boolean create = !IndexReader.indexExists(path);
indexer = new IndexModifier(path, analyzer, create);
indexers.put(path, indexer);
}
}
......@@ -613,6 +615,18 @@ implements Trigger
index[i] = found;
}
}
public void close() throws SQLException {
try {
if (indexer != null) {
indexer.flush();
indexer.close();
indexer = null;
}
} catch (Exception e) {
throw convertException(e);
}
}
//## Java 1.4 end ##
}
......@@ -9,6 +9,7 @@ package org.h2.schema;
import java.sql.Connection;
import java.sql.SQLException;
import org.h2.api.CloseListener;
import org.h2.api.Trigger;
import org.h2.command.Parser;
import org.h2.constant.ErrorCode;
......@@ -313,7 +314,7 @@ public class TriggerObject extends SchemaObjectBase {
}
/**
* Get the trigger class name
* Get the trigger class name.
*
* @return the class name
*/
......@@ -321,4 +322,15 @@ public class TriggerObject extends SchemaObjectBase {
return triggerClassName;
}
/**
* Close the trigger.
*/
public void close() throws SQLException {
if (triggerCallback != null) {
if (triggerCallback instanceof CloseListener) {
((CloseListener) triggerCallback).close();
}
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论