IDEMPIERE-6123 Query in search window causing slowness and load spikes in the database (FHCA-5356) (#2340)

* IDEMPIERE-6123 Query in search window causing slowness and load spikes in the database (FHCA-5356)

* - create SysConfig
- add Dialog when reaching max query records

* - minor fix comment
- add timeout management to MLookup query

* - Fix for the GridTable.Loader.Open issue

* - add SysConfig and Messages
- add showing error message when the number of records loaded in background exceed the allowed
- add timeout to GridTable.fillBuffer

---------

Co-authored-by: hengsin <hengsin@gmail.com>
This commit is contained in:
Carlos Ruiz 2024-05-03 12:51:47 +02:00
parent 766ca60cd4
commit 42e998ff7d
10 changed files with 215 additions and 90 deletions

View File

@ -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')
;

View File

@ -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')
;

View File

@ -257,10 +257,9 @@ public final class DataStatusEvent extends EventObject implements Serializable
retValue.append(m_currentRow+1); retValue.append(m_currentRow+1);
// of // of
retValue.append("/"); retValue.append("/");
if (m_allLoaded) if (! m_allLoaded)
retValue.append(m_totalRows); retValue.append(m_loadedRows).append("->");
else retValue.append(m_totalRows);
retValue.append(m_loadedRows).append("->").append(m_totalRows);
// //
return retValue.toString(); return retValue.toString();
} // getMessage } // getMessage
@ -358,6 +357,7 @@ public final class DataStatusEvent extends EventObject implements Serializable
e.m_changedColumn == m_changedColumn && e.m_changedColumn == m_changedColumn &&
Util.equals(e.m_columnName, m_columnName) && Util.equals(e.m_columnName, m_columnName) &&
e.m_currentRow == m_currentRow && e.m_currentRow == m_currentRow &&
e.m_loadedRows == m_loadedRows &&
e.isInitEdit == isInitEdit; e.isInitEdit == isInitEdit;
} }

View File

@ -235,6 +235,8 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
public static final String CTX_IsLookupOnlySelection = "_TabInfo_IsLookupOnlySelection"; public static final String CTX_IsLookupOnlySelection = "_TabInfo_IsLookupOnlySelection";
public static final String CTX_IsAllowAdvancedLookup = "_TabInfo_IsAllowAdvancedLookup"; public static final String CTX_IsAllowAdvancedLookup = "_TabInfo_IsAllowAdvancedLookup";
public static final int DEFAULT_GLOBAL_MAX_QUERY_RECORDS = 100000;
/** /**
* Tab loader for Tabs > 0 * Tab loader for Tabs > 0
*/ */
@ -2544,20 +2546,23 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
} }
// Row Count // Row Count
int rows = getRowCount(); int rows = getRowCount();
if (rows == 0) if (rows == 0 && !m_mTable.isLoading())
{ {
log.fine("No Rows"); log.fine("No Rows");
return -1; return -1;
} }
if (newRow >= rows) if (newRow >= rows)
{ {
newRow = rows-1; if (!m_mTable.isLoading())
if (log.isLoggable(Level.FINE)) log.fine("Set to max Row: " + newRow); {
newRow = rows-1;
if (log.isLoggable(Level.FINE)) log.fine("Set to max Row: " + newRow);
}
} }
else if (newRow < 0) else if (newRow < 0)
{ {
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); m_mTable.waitLoadingForRow(newRow);
@ -3556,6 +3561,9 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
int tabMaxQueryRecords = m_vo.MaxQueryRecords; int tabMaxQueryRecords = m_vo.MaxQueryRecords;
if (roleMaxQueryRecords > 0 && (roleMaxQueryRecords < tabMaxQueryRecords || tabMaxQueryRecords == 0)) if (roleMaxQueryRecords > 0 && (roleMaxQueryRecords < tabMaxQueryRecords || tabMaxQueryRecords == 0))
tabMaxQueryRecords = roleMaxQueryRecords; 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; return tabMaxQueryRecords;
} }

View File

@ -46,6 +46,7 @@ import java.util.logging.Level;
import javax.swing.event.TableModelListener; import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.DBException; import org.adempiere.exceptions.DBException;
import org.adempiere.util.ServerContext; import org.adempiere.util.ServerContext;
import org.compiere.Adempiere; import org.compiere.Adempiere;
@ -95,13 +96,14 @@ public class GridTable extends AbstractTableModel
implements Serializable 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"; 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_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 LOAD_TIMEOUT_ERROR_MESSAGE = "GridTabLoadTimeoutError";
@ -169,6 +171,7 @@ public class GridTable extends AbstractTableModel
/** Rowcount */ /** Rowcount */
private int m_rowCount = 0; private int m_rowCount = 0;
private boolean m_rowCountTimeout = false;
/** Has Data changed? */ /** Has Data changed? */
private boolean m_changed = false; private boolean m_changed = false;
/** Index of changed row via SetValueAt */ /** Index of changed row via SetValueAt */
@ -426,7 +429,8 @@ public class GridTable extends AbstractTableModel
//IDEMPIERE-5193 Add Limit to Query //IDEMPIERE-5193 Add Limit to Query
if(m_maxRows > 0 && DB.getDatabase().isPagingSupported()) 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<Object[]>(m_rowCount+10); m_buffer = new ArrayList<Object[]>(m_rowCount+10);
} }
m_sort = new ArrayList<MSort>(m_rowCount+10); m_sort = new ArrayList<MSort>(m_rowCount+10);
if (m_rowCount > 0) // actual row count or timeout
if (m_rowCount > 0 || m_rowCountTimeout)
{ {
m_loader.setContext(ServerContext.getCurrentInstance()); m_loader.setContext(ServerContext.getCurrentInstance());
m_loaderFuture = Adempiere.getThreadPoolExecutor().submit(m_loader); 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); log.warning("Reached " + timeout + " seconds timeout loading row " + (row+1) + " for SQL=" + m_SQL);
//adjust row count //adjust row count
m_rowCount = m_sort.size(); 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 try
{ {
stmt = DB.prepareStatement(sql.toString(), null); 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(); rs = stmt.executeQuery();
while(rs.next()) while(rs.next())
{ {
@ -3015,11 +3023,13 @@ public class GridTable extends AbstractTableModel
rows = 0; rows = 0;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
m_rowCountTimeout = false;
try try
{ {
pstmt = DB.prepareStatement(m_SQL_Count, get_TrxName()); pstmt = DB.prepareStatement(m_SQL_Count, get_TrxName());
setParameter (pstmt, true); 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) if (timeout > 0)
pstmt.setQueryTimeout(timeout); pstmt.setQueryTimeout(timeout);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -3028,7 +3038,13 @@ public class GridTable extends AbstractTableModel
} }
catch (SQLException e0) catch (SQLException e0)
{ {
throw new DBException(e0); if (DB.getDatabase().isQueryTimeout(e0))
{
m_rowCountTimeout = true;
return 0;
}
else
throw new DBException(e0);
} }
finally finally
{ {
@ -3064,11 +3080,7 @@ public class GridTable extends AbstractTableModel
try try
{ {
m_pstmt = DB.prepareStatement(m_SQL, trxName); m_pstmt = DB.prepareStatement(m_SQL, trxName);
if (this.maxRows > 0 && rows == this.maxRows) //ensure not all rows are fetch into memory for virtual table
{
m_pstmt.setMaxRows(this.maxRows);
}
//ensure not all row is fectch into memory for virtual table
if (m_virtual) if (m_virtual)
m_pstmt.setFetchSize(100); m_pstmt.setFetchSize(100);
setParameter (m_pstmt, false); setParameter (m_pstmt, false);
@ -3079,8 +3091,12 @@ public class GridTable extends AbstractTableModel
} }
catch (SQLException e) catch (SQLException e)
{ {
log.saveError(e.getLocalizedMessage(), e); if (DB.getDatabase().isQueryTimeout(e)) {
throw new DBException(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 * Fill buffer from result set
*/ */
private void doRun() { private void doRun() {
boolean isFindOverMax = false;
try try
{ {
openResultSet(); openResultSet();
@ -3126,6 +3143,11 @@ public class GridTable extends AbstractTableModel
while (m_rs.next()) while (m_rs.next())
{ {
if (maxRows > 0 && m_sort.size() == maxRows) {
isFindOverMax = true;
break;
}
if (Thread.interrupted()) if (Thread.interrupted())
{ {
if (log.isLoggable(Level.FINE)) log.fine("Interrupted"); if (log.isLoggable(Level.FINE)) log.fine("Interrupted");
@ -3149,9 +3171,25 @@ public class GridTable extends AbstractTableModel
} }
m_sort.add(sort); 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 // Statement all 1000 rows & sleep
if (m_sort.size() % 1000 == 0) if (m_sort.size() % 1000 == 0)
{ {
DataStatusEvent evt = createDSE();
evt.setLoading(m_sort.size());
fireDataStatusChanged(evt);
// give the other processes a chance // give the other processes a chance
try try
{ {
@ -3164,9 +3202,6 @@ public class GridTable extends AbstractTableModel
close(); close();
return; return;
} }
DataStatusEvent evt = createDSE();
evt.setLoading(m_sort.size());
fireDataStatusChanged(evt);
} }
} // while(rs.next()) } // while(rs.next())
} }
@ -3178,6 +3213,17 @@ public class GridTable extends AbstractTableModel
{ {
close(); 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("", ""); fireDataStatusIEvent("", "");
} }

View File

@ -58,9 +58,9 @@ import org.compiere.util.ValueNamePair;
public final class MLookup extends Lookup implements Serializable 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 * MLookup Constructor
@ -1083,9 +1083,9 @@ public final class MLookup extends Lookup implements Serializable
protected class MLoader extends ContextRunnable 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 * MLoader Constructor
@ -1228,7 +1228,11 @@ public final class MLookup extends Lookup implements Serializable
try try
{ {
// SELECT Key, Value, Name, IsActive FROM ... // 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(); rs = pstmt.executeQuery();
// Get first ... rows // Get first ... rows
@ -1237,19 +1241,10 @@ public final class MLookup extends Lookup implements Serializable
{ {
if (rows++ > MAX_ROWS) if (rows++ > MAX_ROWS)
{ {
StringBuilder s = new StringBuilder().append(m_info.KeyColumn).append(": Loader - Too many records"); logLookup(Level.WARNING, "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());
break; break;
} }
// check for interrupted every 10 rows // check for interrupted every 20 rows
if (rows % 20 == 0 && Thread.interrupted()) if (rows % 20 == 0 && Thread.interrupted())
break; break;
@ -1294,8 +1289,11 @@ public final class MLookup extends Lookup implements Serializable
} }
catch (SQLException e) catch (SQLException e)
{ {
log.log(Level.SEVERE, m_info.KeyColumn + ", " + m_info.Column_ID + " : Loader - " + sql, e);
m_allLoaded = false; m_allLoaded = false;
if (DB.getDatabase().isQueryTimeout(e))
logLookup(Level.WARNING, "Too slow query");
else
logLookup(Level.SEVERE, e.getLocalizedMessage());
} }
finally { finally {
DB.close(rs, pstmt); DB.close(rs, pstmt);
@ -1307,6 +1305,25 @@ public final class MLookup extends Lookup implements Serializable
+ " - ms=" + String.valueOf(System.currentTimeMillis()-m_startTime) + " - ms=" + String.valueOf(System.currentTimeMillis()-m_startTime)
+ " (" + String.valueOf(System.currentTimeMillis()-startTime) + ")"); + " (" + String.valueOf(System.currentTimeMillis()-startTime) + ")");
} // run } // 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 } // Loader
} // MLookup } // MLookup

View File

@ -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) */ /** 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_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_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 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_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_MINIFY = "HTML_REPORT_MINIFY";
public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME"; public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME";
public static final String IBAN_VALIDATION = "IBAN_VALIDATION"; public static final String IBAN_VALIDATION = "IBAN_VALIDATION";

View File

@ -29,7 +29,6 @@ import java.util.logging.Level;
import org.adempiere.base.Core; import org.adempiere.base.Core;
import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.DBException;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.AdempiereIdGenerator;
import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.AdempiereWebUI;
@ -1380,23 +1379,9 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows) public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows)
{ {
boolean open = gridTab.isOpen(); boolean open = gridTab.isOpen();
try gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows);
{ if (listPanel.isVisible() && !open)
gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows); gridTab.getTableModel().fireTableDataChanged();
if (listPanel.isVisible() && !open)
gridTab.getTableModel().fireTableDataChanged();
}
catch (Exception e)
{
if (DBException.isTimeout(e))
{
throw e;
}
else
{
Dialog.error(windowNo, e.getMessage());
}
}
} }
/** /**

View File

@ -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_REDO;
import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_UNDO; import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_UNDO;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -853,15 +855,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
} }
} }
// //
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM ") int no = getRecordCount(mTab, where);
.append(mTab.getTableName()); // show find dialog if count timeout/exception
if (where.length() > 0) require = no == -1 ? true : mTab.isQueryRequire(no);
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);
} }
// Show find window (if required) // Show find window (if required)
@ -916,6 +912,35 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
} }
} // initialQuery } // 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 * Setup find window UI properties
* @param findWindow * @param findWindow
@ -1742,7 +1767,16 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
{ {
//ignore non-ui thread event. //ignore non-ui thread event.
if (Executions.getCurrent() == null) 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; return;
}
boolean detailTab = false; boolean detailTab = false;
if (e.getSource() instanceof GridTable) if (e.getSource() instanceof GridTable)

View File

@ -3020,14 +3020,10 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
// Test for no records // Test for no records
if (getNoOfRecords(m_query, true) != 0) { if (getNoOfRecords(m_query, true) != 0) {
if (m_total == COUNTING_RECORDS_TIMED_OUT) { if (advancedPanel != null) {
Dialog.error(m_targetWindowNo, "InfoQueryTimeOutError"); advancedPanel.getItems().clear();
} else {
if (advancedPanel != null) {
advancedPanel.getItems().clear();
}
dispose();
} }
dispose();
} }
} // cmd_ok_Simple } // cmd_ok_Simple
@ -3098,11 +3094,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
} }
if (getNoOfRecords(m_query, true) != 0) { if (getNoOfRecords(m_query, true) != 0) {
if (m_total == COUNTING_RECORDS_TIMED_OUT) { dispose();
Dialog.error(m_targetWindowNo, "InfoQueryTimeOutError");
} else {
dispose();
}
} }
} // cmd_ok_Advanced } // cmd_ok_Advanced
@ -3150,8 +3142,8 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL); Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL);
// Execute Query // Execute Query
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_INITIAL_COUNT_TIMEOUT_IN_SECONDS,
GridTable.DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx())); GridTable.DEFAULT_GRIDTABLE_COUNT_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx()));
m_total = 999999; m_total = 999999;
Statement stmt = null; Statement stmt = null;
ResultSet rs = null; ResultSet rs = null;
@ -3187,12 +3179,12 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
// No Records // No Records
if (m_total == 0 && alertRecords) if (m_total == 0 && alertRecords)
Dialog.warn(m_targetWindowNo, "FindZeroRecords", null); 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)) if (m_gridTab != null && alertRecords && m_total != COUNTING_RECORDS_TIMED_OUT && m_gridTab.isQueryMax(m_total))
{ {
Dialog.error(m_targetWindowNo, "FindOverMax", Dialog.info(m_targetWindowNo, "FindOverMax",
m_total + " > " + m_gridTab.getMaxQueryRecords()); m_total + " > " + m_gridTab.getMaxQueryRecords());
m_total = 0; // return 0 if more then allowed - teo_sarca [ 1708717 ] m_total = m_gridTab.getMaxQueryRecords();
} }
else else
if (log.isLoggable(Level.CONFIG)) log.config("#" + m_total); if (log.isLoggable(Level.CONFIG)) log.config("#" + m_total);