diff --git a/base/src/org/compiere/model/MTable.java b/base/src/org/compiere/model/MTable.java index de1b93a6c8..acde802e0a 100644 --- a/base/src/org/compiere/model/MTable.java +++ b/base/src/org/compiere/model/MTable.java @@ -727,6 +727,17 @@ public class MTable extends X_AD_Table } return retValue; } + + /** + * Create query to retrieve one or more PO. + * @param whereClause + * @param trxName + * @return Query + */ + public Query createQuery(String whereClause, String trxName) + { + return new Query(this, whereClause, trxName); + } /** * String Representation diff --git a/base/src/org/compiere/model/POIterator.java b/base/src/org/compiere/model/POIterator.java new file mode 100644 index 0000000000..b72e7ee711 --- /dev/null +++ b/base/src/org/compiere/model/POIterator.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Product: Adempiere ERP & CRM Smart Business Solution * Copyright (C) + * 1999-2006 Adempiere, Inc. All Rights Reserved. * This program is free + * software; you can redistribute it and/or modify it * under the terms version + * 2 of the GNU General Public License as published * by the Free Software + * Foundation. This program 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 General + * Public License for more details. * You should have received a copy of the GNU + * General Public License along * with this program; if not, write to the Free + * Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. * + * + * Copyright (C) 2007 Low Heng Sin hengsin@avantz.com + * Contributor(s): + * __________________________________________ + ******************************************************************************/ +package org.compiere.model; + +import java.util.Iterator; +import java.util.List; + +import org.compiere.util.Env; + +/** + * + * Iterator implementation to fetch PO one at a time using a prefetch ID list. + * @author Low Heng Sin + * + */ +public class POIterator implements Iterator { + + private MTable table; + private List idList; + + private int iteratorIndex = -1; + private String trxName; + + private String keyWhereClause = null; + + /** + * @param table + * @param idList + * @param trxName + */ + public POIterator(MTable table, List idList, String trxName) { + this.table = table; + this.idList = idList; + this.trxName = trxName; + } + + /** + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + return ( iteratorIndex < (idList.size() - 1)); + } + + /** + * @see java.util.Iterator#next() + */ + public PO next() { + if ( iteratorIndex < (idList.size() - 1)) { + iteratorIndex ++; + return get(iteratorIndex); + } else { + return null; + } + } + + /** + * not supported. + */ + public void remove() { + throw new UnsupportedOperationException("Remove operatiotn not supported."); + } + + /** + * @return number of records + */ + public int size() { + return idList.size(); + } + + /** + * @param index + * @return PO or null if index is invalid + */ + public PO get(int index) { + if (index <= (idList.size() - 1)) { + Object[] ids = idList.get(index); + if (ids.length == 1 && ids[0] instanceof Integer) { + return table.getPO((Integer)ids[0], trxName); + } else { + if (keyWhereClause == null) { + String[] keys = table.getKeyColumns(); + POInfo info = POInfo.getPOInfo(Env.getCtx(), table.getAD_Table_ID()); + if (info == null) return null; + StringBuffer sqlBuffer = info.buildSelect(); + sqlBuffer.append(" WHERE "); + for (int i = 0; i < keys.length; i++) { + if (i > 0) + sqlBuffer.append(" AND "); + sqlBuffer.append(keys[i]).append(" = ? "); + } + keyWhereClause = sqlBuffer.toString(); + } + return table.getPO(keyWhereClause, ids, trxName); + } + } else { + return null; + } + } +} diff --git a/base/src/org/compiere/model/POResultSet.java b/base/src/org/compiere/model/POResultSet.java new file mode 100644 index 0000000000..9cea15b059 --- /dev/null +++ b/base/src/org/compiere/model/POResultSet.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Product: Adempiere ERP & CRM Smart Business Solution * Copyright (C) + * 1999-2006 Adempiere, Inc. All Rights Reserved. * This program is free + * software; you can redistribute it and/or modify it * under the terms version + * 2 of the GNU General Public License as published * by the Free Software + * Foundation. This program 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 General + * Public License for more details. * You should have received a copy of the GNU + * General Public License along * with this program; if not, write to the Free + * Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. * + * + * Copyright (C) 2007 Low Heng Sin hengsin@avantz.com + * Contributor(s): + * __________________________________________ + ******************************************************************************/ +package org.compiere.model; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Simple wrapper over jdbc resultset + * @author Low Heng Sin + * + */ +public class POResultSet { + + private String trxName; + private ResultSet resultSet; + private MTable table; + private PreparedStatement statement; + + /** + * + * @param table + * @param ps + * @param rs + * @param trxName + */ + public POResultSet(MTable table, PreparedStatement ps, ResultSet rs, String trxName) { + this.table = table; + this.statement = ps; + this.resultSet = rs; + this.trxName = trxName; + } + + /** + * + * @return PO or null if reach the end of resultset + * @throws SQLException + */ + public PO next() throws SQLException { + if ( resultSet.next() ) { + return table.getPO(resultSet, trxName); + } else { + return null; + } + } + + /** + * Release database resources. + */ + public void close() { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + } + } + try { + resultSet.close(); + } catch (SQLException e) { + } + } +} diff --git a/base/src/org/compiere/model/Query.java b/base/src/org/compiere/model/Query.java new file mode 100644 index 0000000000..c508ffa118 --- /dev/null +++ b/base/src/org/compiere/model/Query.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Product: Adempiere ERP & CRM Smart Business Solution * Copyright (C) + * 1999-2006 Adempiere, Inc. All Rights Reserved. * This program is free + * software; you can redistribute it and/or modify it * under the terms version + * 2 of the GNU General Public License as published * by the Free Software + * Foundation. This program 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 General + * Public License for more details. * You should have received a copy of the GNU + * General Public License along * with this program; if not, write to the Free + * Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. * + * + * Copyright (C) 2007 Low Heng Sin hengsin@avantz.com + * Contributor(s): + * __________________________________________ + ******************************************************************************/ +package org.compiere.model; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; +import java.util.logging.Level; + +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; + +/** + * + * @author Low Heng Sin + * + */ +public class Query { + + private static CLogger log = CLogger.getCLogger (Query.class); + + private MTable table = null; + private String whereClause = null; + private String orderBy = null; + private String trxName = null; + private Object[] parameters = null; + + /** + * + * @param table + * @param whereClause + * @param trxName + */ + public Query(MTable table, String whereClause, String trxName) { + this.table = table; + this.whereClause = whereClause; + this.trxName = trxName; + } + + /** + * Set query parameters + * @param parameters + */ + public void setParameters(Object[] parameters) { + this.parameters = parameters; + } + + /** + * Set order by clause ( without the order by sql keyword ). + * @param orderBy + */ + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + /** + * Return a list of all po that match the query criteria. + * @return List + */ + public List list() { + List list = new ArrayList(); + + POInfo info = POInfo.getPOInfo(Env.getCtx(), table.getAD_Table_ID()); + if (info == null) return null; + StringBuffer sqlBuffer = info.buildSelect(); + if (whereClause != null && whereClause.trim().length() > 0) + sqlBuffer.append(" WHERE ").append(whereClause); + if (orderBy != null && orderBy.trim().length() > 0) + sqlBuffer.append(" Order By ").append(orderBy); + String sql = sqlBuffer.toString(); + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (parameters != null && parameters.length > 0) + { + for (int i = 0; i < parameters.length; i++) + { + pstmt.setObject(i+1, parameters[i]); + } + } + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + PO po = table.getPO(rs, trxName); + list.add(po); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + log.saveError("Error", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return list; + } + + /** + * Return an Iterator implementation to fetch one PO at a time. The implementation first retrieve + * all IDS that match the query criteria and issue sql query to fetch the PO when caller want to + * fetch the next PO. This minimize memory usage but it is slower than the list method. + * @return Iterator + */ + public Iterator iterate() { + String[] keys = table.get_KeyColumns(); + StringBuffer sqlBuffer = new StringBuffer(" SELECT "); + for (int i = 0; i < keys.length; i++) { + if (i > 0) + sqlBuffer.append(", "); + sqlBuffer.append(keys[i]); + } + sqlBuffer.append(" FROM ").append(table.get_TableName()); + if (whereClause != null && whereClause.trim().length() > 0) + sqlBuffer.append(" WHERE ").append(whereClause); + if (orderBy != null && orderBy.trim().length() > 0) + sqlBuffer.append(" Order By ").append(orderBy); + String sql = sqlBuffer.toString(); + PreparedStatement pstmt = null; + List idList = new ArrayList(); + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (parameters != null && parameters.length > 0) + { + for (int i = 0; i < parameters.length; i++) + { + pstmt.setObject(i+1, parameters[i]); + } + } + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + Object[] ids = new Object[keys.length]; + for (int i = 0; i < ids.length; i++) { + ids[i] = rs.getObject(i+1); + } + idList.add(ids); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + log.saveError("Error", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return new POIterator(table, idList, trxName); + } + + /** + * Return a simple wrapper over a jdbc resultset. It is the caller responsibility to + * call the close method to release the underlying database resources. + * @return POResultSet + */ + public POResultSet scroll() { + POInfo info = POInfo.getPOInfo(Env.getCtx(), table.getAD_Table_ID()); + if (info == null) return null; + StringBuffer sqlBuffer = info.buildSelect(); + if (whereClause != null && whereClause.trim().length() > 0) + sqlBuffer.append(" WHERE ").append(whereClause); + if (orderBy != null && orderBy.trim().length() > 0) + sqlBuffer.append(" Order By ").append(orderBy); + String sql = sqlBuffer.toString(); + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (parameters != null && parameters.length > 0) + { + for (int i = 0; i < parameters.length; i++) + { + pstmt.setObject(i+1, parameters[i]); + } + } + ResultSet rs = pstmt.executeQuery (); + return new POResultSet(table, pstmt, rs, trxName); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + log.saveError("Error", e); + } + return null; + } +}