📄 sqlclauseset.java
字号:
/*
* Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.mandarax.sql;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.apache.commons.collections.iterators.SingletonIterator;
import org.mandarax.kernel.AbstractPropertiesSupport;
import org.mandarax.kernel.Clause;
import org.mandarax.kernel.ClauseSet;
import org.mandarax.kernel.ClauseSetChangeListener;
import org.mandarax.kernel.ClauseSetException;
import org.mandarax.kernel.Predicate;
import org.mandarax.util.logging.LogCategories;
/**
* An SQL clause set is basically a wrapper around a ResultSet of an SQL query where each
* row in the result set is considered as a single clause (fact).
* @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
* @version 3.4 <7 March 05>
* @since 1.5
*/
public class SQLClauseSet extends AbstractPropertiesSupport implements ClauseSet, LogCategories {
private String whereClause = "";
private SQLPredicate predicate = null;
private String query = null;
private List cache = null;
private long cacheTimeout = NO_CACHE;
private long cacheTimestamp = 0;
public static final int NO_CACHE = -1;
private boolean closeConnection = true;
/**
* Constructor.
*/
public SQLClauseSet() {
super();
}
/**
* Constructor.
* @p a predicate
*/
public SQLClauseSet(SQLPredicate p) {
this(p, NO_CACHE);
}
/**
* Constructor.
* @param p a predicate
* @param where a where clause
*/
public SQLClauseSet(SQLPredicate p, String where) {
this(p, where, NO_CACHE);
}
/**
* Constructor.
* @param p a predicate
* @param timeout the timeout after which the cache expires, if NO_CACHE , no caching is done
*/
public SQLClauseSet(SQLPredicate p, long timeout) {
this(p, "", timeout);
}
/**
* Constructor.
* @param p a predicate
* @param where a where clause
* @param timeout the timeout after which the cache expires, if NO_CACHE , no caching is done
*/
public SQLClauseSet(SQLPredicate p, String where, long timeout) {
super();
predicate = p;
whereClause = where;
cacheTimeout = timeout;
}
/**
* Add a clause set listener.
* @param l the listener
*/
public void addClauseSetChangeListener(ClauseSetChangeListener l) {
}
/**
* Iterate over all clauses.
* @return a clause iterator
* @throws ClauseSetException
*/
public org.mandarax.util.ClauseIterator clauses() throws ClauseSetException {
try {
if (useCache()) {
return new CachedClauseIterator(cache);
}
else {
String query = getQuery();
Connection con = predicate.getDataSource().getConnection();
LOG_SQL.debug("Execute SQL: " + query);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
// next line bugfix 1.9
if (cacheTimeout != NO_CACHE) {
cache = new Vector();
cacheTimestamp = System.currentTimeMillis();
}
return new SQLClauseIterator(predicate, rs, cache,closeConnection,con);
}
}
catch (Exception x) {
LOG_SQL.error("Exception executing SQL", x);
throw new ClauseSetException("Exception building clause from SQL",x);
}
}
/**
* Get an iterator for clauses. The clause passed represents a query
* which can be used to restrict the clause set. E.g., if the clause
* iterator is built from database objects, and some of the variables
* in the query clause are already replaced by constants, these constants
* might be used to form a <code>WHERE</code> clause restricting the set of database objects
* used to establish the clauses. The additional parameter provides a general
* purpose interface to pass additional information, e.g. to sort the clause
* set.
* @return a clause iterator
* @param query the query clause
* @param additionalParameter an optional additional parameter
* @throws ClauseSetException
*/
public org.mandarax.util.ClauseIterator clauses(Clause query, Object additionalParameter) throws ClauseSetException {
return clauses();
}
/**
* Get a key for indexing. The knowledge base is supposed to
* contain only clauses having the same key object. This method
* returns this key object. Note that this behavior is not enforced!
* @see org.mandarax.kernel.Fact#getKey
* @see org.mandarax.kernel.Rule#getKey
* @see org.mandarax.kernel.KnowledgeBase
* @return the key object
*/
public Object getKey() {
return predicate;
}
/**
* Get the predicate.
* @return a predicate
*/
public Predicate getPredicate() {
return predicate;
}
/**
* Get the query build from the SELECT statement from the predicate
* plus the additional WHERE clause set here.
* @return a query
*/
public String getQuery() {
if (query == null) {
String q = predicate.getQuery().trim();
String w = getWhereClause();
if (w != null) {
w = w.trim();
if (w.length() > 0) {
if (w.toLowerCase().indexOf("where") == 0) {
q = q + " " + w;
}
else {
q = q + " where " + w;
}
}
}
query = q;
}
return query;
}
/**
* Get the where clause
* @return the where clause
*/
public String getWhereClause() {
return whereClause;
}
/**
* Remove a clause set listener.
* @param l the listener
*/
public void removeClauseSetChangeListener(ClauseSetChangeListener l) {
}
/**
* Set a predicate.
* @param p a predicate
*/
public void setPredicate(Predicate p) {
if (p instanceof SQLPredicate) setSQLPredicate((SQLPredicate)p);
else throw new IllegalArgumentException("SQLClauseSets expect SQLPredicates");
}
/**
* Set an SQL predicate.
* @param p a predicate
*/
public void setSQLPredicate(SQLPredicate p) {
predicate = p;
}
/**
* Set a WHERE clause.
* @param p a predicate
*/
public void setWhereClause(String c) {
whereClause = c;
query = null;
}
/**
* Indicates whether the cache can be used.
* @return a boolean
*/
private boolean useCache() {
if (cache == null) {
return false;
}
else {
if (cacheTimeout == NO_CACHE) {
cache = null;
return false;
}
else {
// check whether cache is expired
if ((System.currentTimeMillis() - cacheTimestamp) > (cacheTimeout * 1000)) {
cache = null;
return false;
}
else {
return true;
}
}
}
}
/**
* Sets whether to close the connection at the end.
* @param closeConnection a boolean
*/
public void setCloseConnection(boolean closeConnection) {
this.closeConnection = closeConnection;
}
/**
* Set the cache time out. The cache expires after this time.
* @param a timeout in milli seconds, use NO_CACHE in order to switch caching off
*/
public void setCacheTimeout(long timeout) {
cacheTimeout = timeout;
}
/**
* Get the cache time out. The cache expires after this time.
* @return a timeout in milli seconds, NO_CACHE indicates that there is no caching
*/
public long getCacheTimeout() {
return cacheTimeout;
}
/**
* Compare objects.
* @param obj another object
* @return a boolean
*/
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof SQLClauseSet)) {
SQLClauseSet c = (SQLClauseSet) obj;
boolean result = true;
// compare query, name and data source
// bugfix in 1.8 - thanks to chenjb@gsta.com
result = (predicate == null) ? (c.predicate == null) : predicate.equals(c.predicate);
result = result && ((whereClause == null) ? (c.whereClause == null) : whereClause.equals(c.whereClause));
result = result && ((cacheTimeout == c.cacheTimeout));
result = result && (closeConnection==c.closeConnection);
return result;
}
else {
return false;
}
}
/**
* Get the hashcode of the object.
* @return the hash code of the object
*/
public int hashCode() {
return ((predicate == null) ? 0 : predicate.hashCode())
^ ((whereClause == null) ? 0 : whereClause.hashCode());
}
/**
* Indicates whether to close the connection at the end.
* @return a boolean
*/
public boolean isCloseConnection() {
return closeConnection;
}
/**
* Get an iterator iterating over the predicates contained in this clause set.
* @return an iterator
*/
public Iterator predicates() {
return new SingletonIterator(predicate);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -