diff --git a/migration/iD11/oracle/202404302320_IDEMPIERE-6123.sql b/migration/iD11/oracle/202404302320_IDEMPIERE-6123.sql new file mode 100644 index 0000000000..2d3aacce8e --- /dev/null +++ b/migration/iD11/oracle/202404302320_IDEMPIERE-6123.sql @@ -0,0 +1,22 @@ +-- IDEMPIERE-6123 Query in search window causing slowness and load spikes in the database (FHCA-5356) +SELECT register_migration_script('202404302320_IDEMPIERE-6123.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Apr 30, 2024, 11:20:08 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200244,0,0,TO_TIMESTAMP('2024-04-30 23:20:08','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2024-04-30 23:20:08','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS','1','Timeout for the initial count on windows','D','C','5fae1af7-74ca-41d8-bbd3-d506c6c23b6a') +; + +-- Apr 30, 2024, 11:22:16 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200245,0,0,TO_TIMESTAMP('2024-04-30 23:22:16','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2024-04-30 23:22:16','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','GLOBAL_MAX_QUERY_RECORDS','100000','Maximum number of records allowed to search in a window, can be overriden per Role or Tab','D','C','840fb67c-4609-41f2-9e20-e0ea9d839065') +; + +-- Apr 30, 2024, 11:23:28 PM CEST +UPDATE AD_Message SET MsgText='The query returned more records than allowed, consider adding more filters.',Updated=TO_TIMESTAMP('2024-04-30 23:23:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=852 +; + +-- Apr 30, 2024, 11:24:06 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','The initial count query timed out, loading records ...',0,0,'Y',TO_TIMESTAMP('2024-04-30 23:24:06','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-04-30 23:24:06','YYYY-MM-DD HH24:MI:SS'),100,200887,'CountQueryTimeoutLoadBackground','D','988292d7-175f-41c2-b560-43d62b8326a9') +; + diff --git a/migration/iD11/postgresql/202404302320_IDEMPIERE-6123.sql b/migration/iD11/postgresql/202404302320_IDEMPIERE-6123.sql new file mode 100644 index 0000000000..ad27fcaac4 --- /dev/null +++ b/migration/iD11/postgresql/202404302320_IDEMPIERE-6123.sql @@ -0,0 +1,19 @@ +-- IDEMPIERE-6123 Query in search window causing slowness and load spikes in the database (FHCA-5356) +SELECT register_migration_script('202404302320_IDEMPIERE-6123.sql') FROM dual; + +-- Apr 30, 2024, 11:20:08 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200244,0,0,TO_TIMESTAMP('2024-04-30 23:20:08','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2024-04-30 23:20:08','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS','1','Timeout for the initial count on windows','D','C','5fae1af7-74ca-41d8-bbd3-d506c6c23b6a') +; + +-- Apr 30, 2024, 11:22:16 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200245,0,0,TO_TIMESTAMP('2024-04-30 23:22:16','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2024-04-30 23:22:16','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','GLOBAL_MAX_QUERY_RECORDS','100000','Maximum number of records allowed to search in a window, can be overriden per Role or Tab','D','C','840fb67c-4609-41f2-9e20-e0ea9d839065') +; + +-- Apr 30, 2024, 11:23:28 PM CEST +UPDATE AD_Message SET MsgText='The query returned more records than allowed, consider adding more filters.',Updated=TO_TIMESTAMP('2024-04-30 23:23:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=852 +; + +-- Apr 30, 2024, 11:24:06 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','The initial count query timed out, loading records ...',0,0,'Y',TO_TIMESTAMP('2024-04-30 23:24:06','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-04-30 23:24:06','YYYY-MM-DD HH24:MI:SS'),100,200887,'CountQueryTimeoutLoadBackground','D','988292d7-175f-41c2-b560-43d62b8326a9') +; + diff --git a/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java b/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java index 5fbbb1e161..313c44331c 100644 --- a/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java +++ b/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java @@ -257,10 +257,9 @@ public final class DataStatusEvent extends EventObject implements Serializable retValue.append(m_currentRow+1); // of retValue.append("/"); - if (m_allLoaded) - retValue.append(m_totalRows); - else - retValue.append(m_loadedRows).append("->").append(m_totalRows); + if (! m_allLoaded) + retValue.append(m_loadedRows).append("->"); + retValue.append(m_totalRows); // return retValue.toString(); } // getMessage @@ -358,6 +357,7 @@ public final class DataStatusEvent extends EventObject implements Serializable e.m_changedColumn == m_changedColumn && Util.equals(e.m_columnName, m_columnName) && e.m_currentRow == m_currentRow && + e.m_loadedRows == m_loadedRows && e.isInitEdit == isInitEdit; } diff --git a/org.adempiere.base/src/org/compiere/model/GridTab.java b/org.adempiere.base/src/org/compiere/model/GridTab.java index 29297e0e24..359186de4a 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTab.java +++ b/org.adempiere.base/src/org/compiere/model/GridTab.java @@ -235,6 +235,8 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable public static final String CTX_IsLookupOnlySelection = "_TabInfo_IsLookupOnlySelection"; public static final String CTX_IsAllowAdvancedLookup = "_TabInfo_IsAllowAdvancedLookup"; + public static final int DEFAULT_GLOBAL_MAX_QUERY_RECORDS = 100000; + /** * Tab loader for Tabs > 0 */ @@ -2544,20 +2546,23 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable } // Row Count int rows = getRowCount(); - if (rows == 0) + if (rows == 0 && !m_mTable.isLoading()) { log.fine("No Rows"); return -1; } if (newRow >= rows) { - newRow = rows-1; - if (log.isLoggable(Level.FINE)) log.fine("Set to max Row: " + newRow); + if (!m_mTable.isLoading()) + { + newRow = rows-1; + if (log.isLoggable(Level.FINE)) log.fine("Set to max Row: " + newRow); + } } else if (newRow < 0) { newRow = 0; - log.fine("Set to first Row"); + if (log.isLoggable(Level.FINE)) log.fine("Set to first Row"); } m_mTable.waitLoadingForRow(newRow); @@ -3556,6 +3561,9 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable int tabMaxQueryRecords = m_vo.MaxQueryRecords; if (roleMaxQueryRecords > 0 && (roleMaxQueryRecords < tabMaxQueryRecords || tabMaxQueryRecords == 0)) tabMaxQueryRecords = roleMaxQueryRecords; + if (tabMaxQueryRecords == 0) + tabMaxQueryRecords = MSysConfig.getIntValue(MSysConfig.GLOBAL_MAX_QUERY_RECORDS, + DEFAULT_GLOBAL_MAX_QUERY_RECORDS, Env.getAD_Client_ID(Env.getCtx())); return tabMaxQueryRecords; } diff --git a/org.adempiere.base/src/org/compiere/model/GridTable.java b/org.adempiere.base/src/org/compiere/model/GridTable.java index 7893bc8355..a460c96e18 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTable.java +++ b/org.adempiere.base/src/org/compiere/model/GridTable.java @@ -46,6 +46,7 @@ import java.util.logging.Level; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; +import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.adempiere.util.ServerContext; import org.compiere.Adempiere; @@ -95,14 +96,15 @@ public class GridTable extends AbstractTableModel implements Serializable { /** - * generated serial id + * */ - private static final long serialVersionUID = -5564364545827057092L; + private static final long serialVersionUID = -2602189278069194311L; protected static final String SORTED_DSE_EVENT = "Sorted"; public static final int DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = 30; - + public static final int DEFAULT_GRIDTABLE_COUNT_TIMEOUT_IN_SECONDS = 1; + public static final String LOAD_TIMEOUT_ERROR_MESSAGE = "GridTabLoadTimeoutError"; public static final String DATA_REFRESH_MESSAGE = "Refreshed"; @@ -169,6 +171,7 @@ public class GridTable extends AbstractTableModel /** Rowcount */ private int m_rowCount = 0; + private boolean m_rowCountTimeout = false; /** Has Data changed? */ private boolean m_changed = false; /** Index of changed row via SetValueAt */ @@ -426,7 +429,8 @@ public class GridTable extends AbstractTableModel //IDEMPIERE-5193 Add Limit to Query if(m_maxRows > 0 && DB.getDatabase().isPagingSupported()) { - m_SQL = DB.getDatabase().addPagingSQL(m_SQL, 1, m_maxRows); + // set to maxRows plus one to trigger FindOverMax on overflow + m_SQL = DB.getDatabase().addPagingSQL(m_SQL, 1, m_maxRows+1); } // @@ -645,7 +649,8 @@ public class GridTable extends AbstractTableModel m_buffer = new ArrayList(m_rowCount+10); } m_sort = new ArrayList(m_rowCount+10); - if (m_rowCount > 0) + // actual row count or timeout + if (m_rowCount > 0 || m_rowCountTimeout) { m_loader.setContext(ServerContext.getCurrentInstance()); m_loaderFuture = Adempiere.getThreadPoolExecutor().submit(m_loader); @@ -1159,7 +1164,7 @@ public class GridTable extends AbstractTableModel log.warning("Reached " + timeout + " seconds timeout loading row " + (row+1) + " for SQL=" + m_SQL); //adjust row count m_rowCount = m_sort.size(); - throw new DBException("GridTabLoadTimeoutError"); + throw new AdempiereException(Msg.getMsg(Env.getCtx(), LOAD_TIMEOUT_ERROR_MESSAGE)); } } @@ -1266,6 +1271,9 @@ public class GridTable extends AbstractTableModel try { stmt = DB.prepareStatement(sql.toString(), null); + int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); + if (timeout > 0) + stmt.setQueryTimeout(timeout); rs = stmt.executeQuery(); while(rs.next()) { @@ -3014,12 +3022,14 @@ public class GridTable extends AbstractTableModel // Get Number of Rows rows = 0; PreparedStatement pstmt = null; - ResultSet rs = null; + ResultSet rs = null; + m_rowCountTimeout = false; try { pstmt = DB.prepareStatement(m_SQL_Count, get_TrxName()); setParameter (pstmt, true); - int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); + int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS, + DEFAULT_GRIDTABLE_COUNT_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); if (timeout > 0) pstmt.setQueryTimeout(timeout); rs = pstmt.executeQuery(); @@ -3028,7 +3038,13 @@ public class GridTable extends AbstractTableModel } catch (SQLException e0) { - throw new DBException(e0); + if (DB.getDatabase().isQueryTimeout(e0)) + { + m_rowCountTimeout = true; + return 0; + } + else + throw new DBException(e0); } finally { @@ -3064,11 +3080,7 @@ public class GridTable extends AbstractTableModel try { m_pstmt = DB.prepareStatement(m_SQL, trxName); - if (this.maxRows > 0 && rows == this.maxRows) - { - m_pstmt.setMaxRows(this.maxRows); - } - //ensure not all row is fectch into memory for virtual table + //ensure not all rows are fetch into memory for virtual table if (m_virtual) m_pstmt.setFetchSize(100); setParameter (m_pstmt, false); @@ -3079,8 +3091,12 @@ public class GridTable extends AbstractTableModel } catch (SQLException e) { - log.saveError(e.getLocalizedMessage(), e); - throw new DBException(e); + if (DB.getDatabase().isQueryTimeout(e)) { + throw new AdempiereException(Msg.getMsg(Env.getCtx(), LOAD_TIMEOUT_ERROR_MESSAGE), e); + } else { + log.saveError(e.getLocalizedMessage(), e); + throw new DBException(e); + } } } @@ -3118,6 +3134,7 @@ public class GridTable extends AbstractTableModel * Fill buffer from result set */ private void doRun() { + boolean isFindOverMax = false; try { openResultSet(); @@ -3126,6 +3143,11 @@ public class GridTable extends AbstractTableModel while (m_rs.next()) { + if (maxRows > 0 && m_sort.size() == maxRows) { + isFindOverMax = true; + break; + } + if (Thread.interrupted()) { if (log.isLoggable(Level.FINE)) log.fine("Interrupted"); @@ -3149,9 +3171,25 @@ public class GridTable extends AbstractTableModel } m_sort.add(sort); + // Start with rowCount=0, inform loading of first row + if (m_rowCountTimeout) + { + m_rowCount++; + if (m_rowCount == 1) + { + DataStatusEvent evt = createDSE(); + evt.setLoading(m_sort.size()); + evt.setInfo("CountQueryTimeoutLoadBackground", null, false, true); + fireDataStatusChanged(evt); + } + } + // Statement all 1000 rows & sleep if (m_sort.size() % 1000 == 0) { + DataStatusEvent evt = createDSE(); + evt.setLoading(m_sort.size()); + fireDataStatusChanged(evt); // give the other processes a chance try { @@ -3164,9 +3202,6 @@ public class GridTable extends AbstractTableModel close(); return; } - DataStatusEvent evt = createDSE(); - evt.setLoading(m_sort.size()); - fireDataStatusChanged(evt); } } // while(rs.next()) } @@ -3178,6 +3213,17 @@ public class GridTable extends AbstractTableModel { close(); } + + // Background loading without initial rowCount, inform final loaded rows + if (m_rowCountTimeout && m_sort.size() > 0) + { + DataStatusEvent evt = createDSE(); + evt.setLoading(m_sort.size()); + if (isFindOverMax) + evt.setInfo("FindOverMax", " > " + m_sort.size(), false, true); + fireDataStatusChanged(evt); + } + fireDataStatusIEvent("", ""); } diff --git a/org.adempiere.base/src/org/compiere/model/MLookup.java b/org.adempiere.base/src/org/compiere/model/MLookup.java index 65731d521b..756cc922fe 100644 --- a/org.adempiere.base/src/org/compiere/model/MLookup.java +++ b/org.adempiere.base/src/org/compiere/model/MLookup.java @@ -58,9 +58,9 @@ import org.compiere.util.ValueNamePair; public final class MLookup extends Lookup implements Serializable { /** - * generated serial id + * */ - private static final long serialVersionUID = 2288661955135689187L; + private static final long serialVersionUID = 3339750658316918418L; /** * MLookup Constructor @@ -1083,9 +1083,9 @@ public final class MLookup extends Lookup implements Serializable protected class MLoader extends ContextRunnable implements Serializable { /** - * generated serial id + * */ - private static final long serialVersionUID = -7868426685745727939L; + private static final long serialVersionUID = -5752931726580011885L; /** * MLoader Constructor @@ -1228,7 +1228,11 @@ public final class MLookup extends Lookup implements Serializable try { // SELECT Key, Value, Name, IsActive FROM ... - pstmt = DB.prepareStatement(sql.toString(), null); + String sqlFirstRows = DB.getDatabase().addPagingSQL(sql.toString(), 1, MAX_ROWS+1); + pstmt = DB.prepareStatement(sqlFirstRows, null); + int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, GridTable.DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); + if (timeout > 0) + pstmt.setQueryTimeout(timeout); rs = pstmt.executeQuery(); // Get first ... rows @@ -1237,19 +1241,10 @@ public final class MLookup extends Lookup implements Serializable { if (rows++ > MAX_ROWS) { - StringBuilder s = new StringBuilder().append(m_info.KeyColumn).append(": Loader - Too many records"); - if (m_info.Column_ID > 0) - { - MColumn mColumn = MColumn.get(m_info.ctx, m_info.Column_ID); - String column = mColumn.getColumnName(); - s.append(", Column=").append(column); - String tableName = MTable.getTableName(m_info.ctx, mColumn.getAD_Table_ID()); - s.append(", Table=").append(tableName); - } - log.warning(s.toString()); + logLookup(Level.WARNING, "Too many records"); break; } - // check for interrupted every 10 rows + // check for interrupted every 20 rows if (rows % 20 == 0 && Thread.interrupted()) break; @@ -1294,8 +1289,11 @@ public final class MLookup extends Lookup implements Serializable } catch (SQLException e) { - log.log(Level.SEVERE, m_info.KeyColumn + ", " + m_info.Column_ID + " : Loader - " + sql, e); m_allLoaded = false; + if (DB.getDatabase().isQueryTimeout(e)) + logLookup(Level.WARNING, "Too slow query"); + else + logLookup(Level.SEVERE, e.getLocalizedMessage()); } finally { DB.close(rs, pstmt); @@ -1307,6 +1305,25 @@ public final class MLookup extends Lookup implements Serializable + " - ms=" + String.valueOf(System.currentTimeMillis()-m_startTime) + " (" + String.valueOf(System.currentTimeMillis()-startTime) + ")"); } // run + + /** + * Log a warning for the lookup problem found + * @param problem + */ + private void logLookup(Level level, String problem) { + if (log.isLoggable(level)) { + StringBuilder msg = new StringBuilder().append(m_info.KeyColumn).append(": Loader - ").append(problem); + if (m_info.Column_ID > 0) { + MColumn mColumn = MColumn.get(m_info.ctx, m_info.Column_ID); + String column = mColumn.getColumnName(); + msg.append(", Column=").append(column); + String tableName = MTable.getTableName(m_info.ctx, mColumn.getAD_Table_ID()); + msg.append(", Table=").append(tableName); + } + log.log(level, msg.toString()); + } + } + } // Loader } // MLookup diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 4b3277f1e2..eabb6da52d 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -46,7 +46,7 @@ public class MSysConfig extends X_AD_SysConfig /** * */ - private static final long serialVersionUID = -4149262106340017798L; + private static final long serialVersionUID = 8121897973805635995L; /** Constant for Predefine System Configuration Names (in alphabetical order) */ @@ -119,7 +119,9 @@ public class MSysConfig extends X_AD_SysConfig public static final String FORM_SQL_QUERY_LOG_ISSUE = "FORM_SQL_QUERY_LOG_ISSUE"; public static final String FORM_SQL_QUERY_MAX_RECORDS = "FORM_SQL_QUERY_MAX_RECORDS"; public static final String FORM_SQL_QUERY_TIMEOUT_IN_SECONDS = "FORM_SQL_QUERY_TIMEOUT_IN_SECONDS"; + public static final String GLOBAL_MAX_QUERY_RECORDS = "GLOBAL_MAX_QUERY_RECORDS"; public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS"; + public static final String GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS = "GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS"; public static final String HTML_REPORT_MINIFY = "HTML_REPORT_MINIFY"; public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME"; public static final String IBAN_VALIDATION = "IBAN_VALIDATION"; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java index 55111a4247..c27de5daac 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java @@ -29,7 +29,6 @@ import java.util.logging.Level; import org.adempiere.base.Core; import org.adempiere.exceptions.AdempiereException; -import org.adempiere.exceptions.DBException; import org.adempiere.util.Callback; import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.AdempiereWebUI; @@ -1380,23 +1379,9 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows) { boolean open = gridTab.isOpen(); - try - { - gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows); - if (listPanel.isVisible() && !open) - gridTab.getTableModel().fireTableDataChanged(); - } - catch (Exception e) - { - if (DBException.isTimeout(e)) - { - throw e; - } - else - { - Dialog.error(windowNo, e.getMessage()); - } - } + gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows); + if (listPanel.isVisible() && !open) + gridTab.getTableModel().fireTableDataChanged(); } /** diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java index 13dd8c1929..62dafd98de 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java @@ -21,6 +21,8 @@ import static org.compiere.model.MSysConfig.ZK_GRID_AFTER_FIND; import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_REDO; import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_UNDO; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.text.MessageFormat; import java.util.ArrayList; @@ -853,15 +855,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } } // - StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM ") - .append(mTab.getTableName()); - if (where.length() > 0) - sql.append(" WHERE ").append(where); - String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(), - mTab.getTableName(), MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); - int no = DB.getSQLValue(null, finalSQL.toString()); - // - require = mTab.isQueryRequire(no); + int no = getRecordCount(mTab, where); + // show find dialog if count timeout/exception + require = no == -1 ? true : mTab.isQueryRequire(no); } // Show find window (if required) @@ -916,6 +912,35 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } } // initialQuery + /** + * Get record count + * @param mTab + * @param where + * @return record count + */ + private int getRecordCount(GridTab mTab, StringBuffer where) { + StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM ") + .append(mTab.getTableName()); + if (where.length() > 0) + sql.append(" WHERE ").append(where); + String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(), + mTab.getTableName(), MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + int no = -1; + int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS, + GridTable.DEFAULT_GRIDTABLE_COUNT_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); + try (PreparedStatement stmt = DB.prepareStatement(finalSQL, null)) { + if (timeout > 0) + stmt.setQueryTimeout(timeout); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) + no = rs.getInt(1); + } catch (SQLException e) { + logger.log(Level.WARNING, e.getMessage(), e); + no = -1; + } + return no; + } + /** * Setup find window UI properties * @param findWindow @@ -1742,7 +1767,16 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements { //ignore non-ui thread event. if (Executions.getCurrent() == null) + { + // Re-post incremental loading event to UI thread + if (e.isLoading() && e.getSource() != null && e.getSource().equals(adTabbox.getSelectedGridTab().getTableModel())) + { + Executions.schedule(getComponent().getDesktop(), evt -> { + this.dataStatusChanged(e); + }, new Event("onAsynchronousDataStatusChanged")); + } return; + } boolean detailTab = false; if (e.getSource() instanceof GridTable) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java index 0fa9af9f01..74de5c0da7 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java @@ -3020,14 +3020,10 @@ public class FindWindow extends Window implements EventListener, ValueCha // Test for no records if (getNoOfRecords(m_query, true) != 0) { - if (m_total == COUNTING_RECORDS_TIMED_OUT) { - Dialog.error(m_targetWindowNo, "InfoQueryTimeOutError"); - } else { - if (advancedPanel != null) { - advancedPanel.getItems().clear(); - } - dispose(); + if (advancedPanel != null) { + advancedPanel.getItems().clear(); } + dispose(); } } // cmd_ok_Simple @@ -3098,11 +3094,7 @@ public class FindWindow extends Window implements EventListener, ValueCha } if (getNoOfRecords(m_query, true) != 0) { - if (m_total == COUNTING_RECORDS_TIMED_OUT) { - Dialog.error(m_targetWindowNo, "InfoQueryTimeOutError"); - } else { - dispose(); - } + dispose(); } } // cmd_ok_Advanced @@ -3150,8 +3142,8 @@ public class FindWindow extends Window implements EventListener, ValueCha Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL); // Execute Query - int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, - GridTable.DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); + int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS, + GridTable.DEFAULT_GRIDTABLE_COUNT_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); m_total = 999999; Statement stmt = null; ResultSet rs = null; @@ -3187,12 +3179,12 @@ public class FindWindow extends Window implements EventListener, ValueCha // No Records if (m_total == 0 && alertRecords) Dialog.warn(m_targetWindowNo, "FindZeroRecords", null); - // More then allowed + // Load not more than max allow if (m_gridTab != null && alertRecords && m_total != COUNTING_RECORDS_TIMED_OUT && m_gridTab.isQueryMax(m_total)) { - Dialog.error(m_targetWindowNo, "FindOverMax", - m_total + " > " + m_gridTab.getMaxQueryRecords()); - m_total = 0; // return 0 if more then allowed - teo_sarca [ 1708717 ] + Dialog.info(m_targetWindowNo, "FindOverMax", + m_total + " > " + m_gridTab.getMaxQueryRecords()); + m_total = m_gridTab.getMaxQueryRecords(); } else if (log.isLoggable(Level.CONFIG)) log.config("#" + m_total);