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:
parent
766ca60cd4
commit
42e998ff7d
|
|
@ -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')
|
||||
;
|
||||
|
||||
|
|
@ -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')
|
||||
;
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Object[]>(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_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("", "");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -3020,14 +3020,10 @@ public class FindWindow extends Window implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue