IDEMPIERE-4628 Implement configurable query timeout for info window (#532)
* IDEMPIERE-4628 Implement configurable query timeout for info window * IDEMPIERE-4628 Implement configurable query timeout for info window Move migration script from i8.2z to i8.2
This commit is contained in:
parent
1afe4fe0c6
commit
59b83c3361
|
@ -0,0 +1,18 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Jan 18, 2021, 1:40:41 PM MYT
|
||||
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 (200169,0,0,TO_DATE('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_QUERY_TIME_OUT','120','Query timeout in seconds for info window. 0 means no timeout.','D','C','f5953385-1c8a-4df2-92dd-ad46aaeefb8e')
|
||||
;
|
||||
|
||||
-- Jan 18, 2021, 1:47:51 PM MYT
|
||||
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 ('E','The search took too long to return results. Please refine your search criteria.',0,0,'Y',TO_DATE('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,200655,'INFO_QUERY_TIME_OUT_ERROR','D','ea2c33af-7c98-4208-8ed0-ea59b7f0ec58')
|
||||
;
|
||||
|
||||
-- Jan 18, 2021, 2:20:33 PM MYT
|
||||
UPDATE AD_Message SET Value='InfoQueryTimeOutError',Updated=TO_DATE('2021-01-18 14:20:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200655
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202001180600_IDEMPIERE-4628.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
-- Jan 18, 2021, 1:40:41 PM MYT
|
||||
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 (200169,0,0,TO_TIMESTAMP('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_QUERY_TIME_OUT','120','Query timeout in seconds for info window. 0 means no timeout.','D','C','f5953385-1c8a-4df2-92dd-ad46aaeefb8e')
|
||||
;
|
||||
|
||||
-- Jan 18, 2021, 1:47:51 PM MYT
|
||||
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 ('E','The search took too long to return results. Please refine your search criteria.',0,0,'Y',TO_TIMESTAMP('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,200655,'INFO_QUERY_TIME_OUT_ERROR','D','ea2c33af-7c98-4208-8ed0-ea59b7f0ec58')
|
||||
;
|
||||
|
||||
-- Jan 18, 2021, 2:20:33 PM MYT
|
||||
UPDATE AD_Message SET Value='InfoQueryTimeOutError',Updated=TO_TIMESTAMP('2021-01-18 14:20:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200655
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202001180600_IDEMPIERE-4628.sql') FROM dual
|
||||
;
|
|
@ -20,6 +20,7 @@ import java.math.BigDecimal;
|
|||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLTimeoutException;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
@ -468,6 +469,13 @@ public interface AdempiereDatabase
|
|||
*/
|
||||
public String getSQLModify (MTable table, MColumn column, boolean setNullOption);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ex
|
||||
* @return true if ex is caused by query timeout
|
||||
*/
|
||||
public default boolean isQueryTimeout(SQLException ex) {
|
||||
return ex instanceof SQLTimeoutException;
|
||||
}
|
||||
} // AdempiereDatabase
|
||||
|
||||
|
|
|
@ -186,6 +186,7 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR = "ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR";
|
||||
public static final String ZK_GRID_VIEW_USE_DEFER_RENDERING = "ZK_GRID_VIEW_USE_DEFER_RENDERING";
|
||||
public static final String ZK_INFO_NUM_PAGE_PRELOAD = "ZK_INFO_NUM_PAGE_PRELOAD";
|
||||
public static final String ZK_INFO_QUERY_TIME_OUT = "ZK_INFO_QUERY_TIME_OUT";
|
||||
public static final String ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD = "ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD";
|
||||
public static final String ZK_LOGIN_ALLOW_REMEMBER_ME = "ZK_LOGIN_ALLOW_REMEMBER_ME";
|
||||
public static final String ZK_LOGO_LARGE = "ZK_LOGO_LARGE";
|
||||
|
|
|
@ -1930,6 +1930,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
*/
|
||||
protected boolean testCount(boolean promptError)
|
||||
{
|
||||
if (useQueryTimeoutFromSysConfig)
|
||||
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
String dynWhere = getSQLWhere();
|
||||
StringBuilder sql = new StringBuilder (m_sqlMain);
|
||||
|
@ -1971,8 +1974,18 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e instanceof SQLException && DB.getDatabase().isQueryTimeout((SQLException) e))
|
||||
{
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, countSql, e);
|
||||
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Level.SEVERE, countSql, e);
|
||||
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||
}
|
||||
m_count = -2;
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.adempiere.webui.part.ITabOnSelectHandler;
|
|||
import org.adempiere.webui.part.WindowContainer;
|
||||
import org.adempiere.webui.session.SessionManager;
|
||||
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||
import org.adempiere.webui.window.FDialog;
|
||||
import org.compiere.minigrid.ColumnInfo;
|
||||
import org.compiere.minigrid.IDColumn;
|
||||
import org.compiere.model.GridField;
|
||||
|
@ -122,6 +123,7 @@ import org.zkoss.zul.ext.Sortable;
|
|||
*/
|
||||
public abstract class InfoPanel extends Window implements EventListener<Event>, WTableModelListener, Sortable<Object>, IHelpContext
|
||||
{
|
||||
protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -312,7 +314,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
try {
|
||||
int t = Integer.parseInt(pair[1]);
|
||||
if (t > 0)
|
||||
this.queryTimeout = t;
|
||||
setFixedQueryTimeout(t);
|
||||
} catch (Exception e) {}
|
||||
} else if (pair[0].equalsIgnoreCase("pagesize")) {
|
||||
try {
|
||||
|
@ -327,6 +329,15 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set fixed query timeout value, overwrite the value from sysconfig
|
||||
* @param timeout
|
||||
*/
|
||||
public void setFixedQueryTimeout(int timeout) {
|
||||
this.queryTimeout = timeout;
|
||||
useQueryTimeoutFromSysConfig = false;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
if (isLookup())
|
||||
|
@ -465,6 +476,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
protected boolean isAutoComplete = false;
|
||||
|
||||
protected int queryTimeout = 0;
|
||||
protected boolean useQueryTimeoutFromSysConfig = true;
|
||||
|
||||
protected String autoCompleteSearchColumn = null;
|
||||
|
||||
|
@ -898,6 +910,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
}
|
||||
|
||||
private List<Object> readLine(int start, int end) {
|
||||
if (useQueryTimeoutFromSysConfig)
|
||||
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||
|
||||
//cacheStart & cacheEnd - 1 based index, start & end - 0 based index
|
||||
if (getCacheStart() >= 1 && cacheEnd > getCacheStart())
|
||||
{
|
||||
|
@ -995,8 +1010,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
}
|
||||
|
||||
catch (SQLException e)
|
||||
{
|
||||
if (DB.getDatabase().isQueryTimeout(e))
|
||||
{
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, dataSql, e);
|
||||
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Level.SEVERE, dataSql, e);
|
||||
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
finally
|
||||
|
@ -1239,6 +1264,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
*/
|
||||
protected boolean testCount()
|
||||
{
|
||||
if (useQueryTimeoutFromSysConfig)
|
||||
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
String dynWhere = getSQLWhere();
|
||||
StringBuilder sql = new StringBuilder (m_sqlCount);
|
||||
|
@ -1262,6 +1290,8 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(countSql, null);
|
||||
if (queryTimeout > 0)
|
||||
pstmt.setQueryTimeout(queryTimeout);
|
||||
setParameters (pstmt, true);
|
||||
rs = pstmt.executeQuery();
|
||||
|
||||
|
@ -1269,8 +1299,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
m_count = rs.getInt(1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e instanceof SQLException && DB.getDatabase().isQueryTimeout((SQLException) e))
|
||||
{
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, countSql, e);
|
||||
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Level.SEVERE, countSql, e);
|
||||
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||
}
|
||||
m_count = -2;
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -1532,4 +1532,12 @@ public class DB_Oracle implements AdempiereDatabase
|
|||
//
|
||||
return sql.toString();
|
||||
} // getSQLModify
|
||||
|
||||
@Override
|
||||
public boolean isQueryTimeout(SQLException ex) {
|
||||
//java.sql.SQLTimeoutException: ORA-01013: user requested cancel of current operation
|
||||
return "72000".equals(ex.getSQLState()) && ex.getErrorCode() == 1013;
|
||||
}
|
||||
|
||||
|
||||
} // DB_Oracle
|
||||
|
|
|
@ -1422,4 +1422,11 @@ public class DB_PostgreSQL implements AdempiereDatabase
|
|||
return sql.toString();
|
||||
} // getSQLModify
|
||||
|
||||
@Override
|
||||
public boolean isQueryTimeout(SQLException ex) {
|
||||
//org.postgresql.util.PSQLException: ERROR: canceling statement due to user request | SQL Code: 0 | SQL State: 57014
|
||||
return "57014".equals(ex.getSQLState());
|
||||
}
|
||||
|
||||
|
||||
} // DB_PostgreSQL
|
||||
|
|
Loading…
Reference in New Issue