IDEMPIERE-1146 + IDEMPIERE-3234 / Centralized ID not working with na… (#44)

* IDEMPIERE-1146 + IDEMPIERE-3234  / Centralized ID not working with native sequence enabled / PROJECT_ID_USE_CENTRALIZED_ID should take priority higher than SYSTEM_NATIVE_SEQUENCE

* IDEMPIERE-1146 + IDEMPIERE-3234

improve performance not reading MTable and Columns but just a cache
list of tables with EntityType column

* IDEMPIERE-1146 + IDEMPIERE-3234

Remove deprecation as the method is now capable of managin all cases
This commit is contained in:
Carlos Ruiz 2020-05-09 15:13:50 +02:00 committed by GitHub
parent a84c1eac2f
commit 1f3a83c96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 133 deletions

View File

@ -28,6 +28,7 @@ import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
@ -35,6 +36,7 @@ import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.DBException;
import org.compiere.db.CConnection;
import org.compiere.util.CCache;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
@ -54,18 +56,12 @@ public class MSequence extends X_AD_Sequence
/**
*
*/
private static final long serialVersionUID = -2215317912000946608L;
/** Log Level for Next ID Call */
private static final Level LOGLEVEL = Level.ALL;
private static final long serialVersionUID = -750059366190164777L;
private static final int QUERY_TIME_OUT = 30;
private static final String NoYearNorMonth = "-";
/**
* @deprecated please use DB.getNextID (int, String, String)
*/
public static int getNextID (int AD_Client_ID, String TableName)
{
return getNextID(AD_Client_ID, TableName, null);
@ -76,23 +72,15 @@ public class MSequence extends X_AD_Sequence
* Get next number for Key column = 0 is Error.
* @param AD_Client_ID client
* @param TableName table name
* @param trxName deprecated (NOT USED!!)
* @param trxName
* @return next no or (-1=not found, -2=error)
*
* WARNING!! This method doesn't take into account the native sequence setting, it's just to be called from DB.getNextID()
*
* @deprecated please use DB.getNextID (int, String, String)
*/
public static int getNextID (int AD_Client_ID, String TableName, String trxName)
{
if (TableName == null || TableName.length() == 0)
throw new IllegalArgumentException("TableName missing");
int retValue = -1;
boolean isSystemNativeSequence = MSysConfig.getBooleanValue(MSysConfig.SYSTEM_NATIVE_SEQUENCE,false);
// Check AdempiereSys
boolean adempiereSys = false;
if (Ini.isClient())
if (Ini.isClient())
{
adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS);
}
@ -101,13 +89,70 @@ public class MSequence extends X_AD_Sequence
String sysProperty = Env.getCtx().getProperty("AdempiereSys", "N");
adempiereSys = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
}
if (adempiereSys && AD_Client_ID > 11)
adempiereSys = false;
//
if (CLogMgt.isLevel(LOGLEVEL))
s_log.log(LOGLEVEL, TableName + " - AdempiereSys=" + adempiereSys + " [" + trxName + "]");
//begin vpj-cd e-evolution 09/02/2005 PostgreSQL
if (CLogMgt.isLevel(Level.FINER))
s_log.log(Level.FINER, TableName + " - AdempiereSys=" + adempiereSys + " [" + trxName + "]");
if (TableName == null || TableName.length() == 0)
throw new IllegalArgumentException("TableName missing");
int retValue = -1;
// If maintaining official dictionary try to get the ID from http official server
if (adempiereSys) {
boolean isUseCentralizedID = MSysConfig.getBooleanValue(MSysConfig.DICTIONARY_ID_USE_CENTRALIZED_ID, true); // defaults to true
if (isUseCentralizedID) {
if (! isExceptionCentralized(TableName)) {
// get ID from http site
retValue = getNextOfficialID_HTTP(TableName);
if (retValue > 0) {
DB.executeUpdateEx("UPDATE AD_Sequence SET CurrentNextSys = ? + 1 WHERE Name=? AND IsTableID='Y' AND IsAutoSequence='Y'",
new Object[] {retValue, TableName},
trxName);
}
return retValue;
}
} else {
// is an error to get a system ID from local
throw new AdempiereException("System IDs must be always obtained from Centralized ID server");
}
}
boolean queryProjectServer = false;
if (isTableWithEntityType(TableName))
queryProjectServer = true;
if (!queryProjectServer && MSequence.Table_Name.equalsIgnoreCase(TableName))
queryProjectServer = true;
// If not official dictionary try to get the ID from http custom server - if configured
if (queryProjectServer && ( ! adempiereSys ) && ( ! isExceptionCentralized(TableName) ) ) {
boolean isUseProjectCentralizedID = MSysConfig.getBooleanValue(MSysConfig.PROJECT_ID_USE_CENTRALIZED_ID, false); // defaults to false
if (isUseProjectCentralizedID) {
// get ID from http site
retValue = getNextProjectID_HTTP(TableName);
if (retValue > 0) {
DB.executeUpdateEx("UPDATE AD_Sequence SET CurrentNext = GREATEST(CurrentNext, ? + 1) WHERE Name=? AND IsTableID='Y' AND IsAutoSequence='Y'",
new Object[] {retValue, TableName},
trxName);
}
return retValue;
}
}
if (isSystemNativeSequence)
{
retValue = CConnection.get().getDatabase().getNextID(TableName+"_SQ", trxName);
if (retValue == -1) {
// try to create the sequence and try again
MSequence.createTableSequence(Env.getCtx(), TableName, trxName, true);
retValue = CConnection.get().getDatabase().getNextID(TableName+"_SQ", trxName);
}
return retValue;
}
// use AD_Sequence to obtain the next ID
String selectSQL = null;
if (DB.isOracle() == false)
{
@ -160,92 +205,30 @@ public class MSequence extends X_AD_Sequence
+ ")");
if (rs.next())
{
// Get the table
MTable table = MTable.get(Env.getCtx(), TableName);
int AD_Sequence_ID = rs.getInt(4);
boolean gotFromHTTP = false;
// If maintaining official dictionary try to get the ID from http official server
if (adempiereSys) {
String isUseCentralizedID = MSysConfig.getValue(MSysConfig.DICTIONARY_ID_USE_CENTRALIZED_ID, "Y"); // defaults to Y
if ( ( ! isUseCentralizedID.equals("N") ) && ( ! isExceptionCentralized(TableName) ) ) {
// get ID from http site
retValue = getNextOfficialID_HTTP(TableName);
if (retValue > 0) {
PreparedStatement updateSQL = null;
try {
updateSQL = conn.prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = ? + 1 WHERE AD_Sequence_ID = ?");
updateSQL.setInt(1, retValue);
updateSQL.setInt(2, AD_Sequence_ID);
updateSQL.executeUpdate();
} finally {
DB.close(updateSQL);
updateSQL = null;
}
}
gotFromHTTP = true;
}
}
boolean queryProjectServer = false;
if (table.getColumn("EntityType") != null)
queryProjectServer = true;
if (!queryProjectServer && MSequence.Table_Name.equalsIgnoreCase(TableName))
queryProjectServer = true;
// If not official dictionary try to get the ID from http custom server - if configured
if (queryProjectServer && ( ! adempiereSys ) && ( ! isExceptionCentralized(TableName) ) ) {
String isUseProjectCentralizedID = MSysConfig.getValue(MSysConfig.PROJECT_ID_USE_CENTRALIZED_ID, "N"); // defaults to N
if (isUseProjectCentralizedID.equals("Y")) {
// get ID from http site
retValue = getNextProjectID_HTTP(TableName);
if (retValue > 0) {
PreparedStatement updateSQL = null;
try {
updateSQL = conn.prepareStatement("UPDATE AD_Sequence SET CurrentNext = GREATEST(CurrentNext, ? + 1) WHERE AD_Sequence_ID = ?");
updateSQL.setInt(1, retValue);
updateSQL.setInt(2, AD_Sequence_ID);
updateSQL.executeUpdate();
} finally {
DB.close(updateSQL);
updateSQL = null;
}
}
gotFromHTTP = true;
}
}
if (! gotFromHTTP) {
PreparedStatement updateSQL = null;
try
{
int incrementNo = rs.getInt(3);
if (adempiereSys) {
String updateCmd = "UPDATE AD_Sequence SET CurrentNextSys=CurrentNextSys+? WHERE AD_Sequence_ID=?";
if (!DB.isOracle() && !DB.isPostgreSQL())
updateCmd = DB.getDatabase().convertStatement(updateCmd);
updateSQL = conn.prepareStatement(updateCmd);
retValue = rs.getInt(2);
} else {
String updateCmd = "UPDATE AD_Sequence SET CurrentNext=CurrentNext+? WHERE AD_Sequence_ID=?";
if (!DB.isOracle() && !DB.isPostgreSQL())
updateCmd = DB.getDatabase().convertStatement(updateCmd);
updateSQL = conn.prepareStatement(updateCmd);
retValue = rs.getInt(1);
}
updateSQL.setInt(1, incrementNo);
updateSQL.setInt(2, AD_Sequence_ID);
updateSQL.executeUpdate();
} finally {
DB.close(updateSQL);
updateSQL = null;
PreparedStatement updateSQL = null;
try
{
int incrementNo = rs.getInt(3);
if (adempiereSys) {
String updateCmd = "UPDATE AD_Sequence SET CurrentNextSys=CurrentNextSys+? WHERE AD_Sequence_ID=?";
if (!DB.isOracle() && !DB.isPostgreSQL())
updateCmd = DB.getDatabase().convertStatement(updateCmd);
updateSQL = conn.prepareStatement(updateCmd);
retValue = rs.getInt(2);
} else {
String updateCmd = "UPDATE AD_Sequence SET CurrentNext=CurrentNext+? WHERE AD_Sequence_ID=?";
if (!DB.isOracle() && !DB.isPostgreSQL())
updateCmd = DB.getDatabase().convertStatement(updateCmd);
updateSQL = conn.prepareStatement(updateCmd);
retValue = rs.getInt(1);
}
updateSQL.setInt(1, incrementNo);
updateSQL.setInt(2, AD_Sequence_ID);
updateSQL.executeUpdate();
} finally {
DB.close(updateSQL);
updateSQL = null;
}
//if (trx == null)
@ -636,8 +619,8 @@ public class MSequence extends X_AD_Sequence
int seqID = ( definite ? dt.getDefiniteSequence_ID() : dt.getDocNoSequence_ID() );
MSequence seq = new MSequence(Env.getCtx(), seqID, trxName);
if (CLogMgt.isLevel(LOGLEVEL))
s_log.log(LOGLEVEL, "DocType_ID=" + C_DocType_ID + " [" + trxName + "]");
if (CLogMgt.isLevel(Level.FINER))
s_log.log(Level.FINER, "DocType_ID=" + C_DocType_ID + " [" + trxName + "]");
return getDocumentNoFromSeq(seq, trxName, po);
} // getDocumentNo
@ -1387,6 +1370,19 @@ public class MSequence extends X_AD_Sequence
return false;
}
private static CCache<String,String> tablesWithEntityType = new CCache<String,String>(Table_Name, "TablesWithEntityType", 60, 0, false, 0);
private synchronized static boolean isTableWithEntityType(String tableName) {
if (tablesWithEntityType == null || tablesWithEntityType.size() == 0) {
final String sql = "SELECT TableName FROM AD_Table WHERE AD_Table_ID IN (SELECT AD_Table_ID FROM AD_Column WHERE ColumnName='EntityType') ORDER BY TableName";
List<List<Object>> list = DB.getSQLArrayObjectsEx(null, sql);
for (List<Object> row : list) {
tablesWithEntityType.put((String)row.get(0), "");
}
}
return (tablesWithEntityType.get(tableName) != null);
}
@Override
protected boolean beforeSave(boolean newRecord) {
if (isStartNewMonth() && !isStartNewYear())

View File

@ -1823,33 +1823,8 @@ public final class DB
* @param trxName optional Transaction Name
* @return next no
*/
@SuppressWarnings("deprecation")
public static int getNextID (int AD_Client_ID, String TableName, String trxName)
{
boolean SYSTEM_NATIVE_SEQUENCE = MSysConfig.getBooleanValue(MSysConfig.SYSTEM_NATIVE_SEQUENCE,false);
// Check AdempiereSys
boolean adempiereSys = false;
if (Ini.isClient())
{
adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS);
}
else
{
String sysProperty = Env.getCtx().getProperty("AdempiereSys", "N");
adempiereSys = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
}
if(SYSTEM_NATIVE_SEQUENCE && !adempiereSys)
{
int m_sequence_id = CConnection.get().getDatabase().getNextID(TableName+"_SQ", trxName);
if (m_sequence_id == -1) {
// try to create the sequence and try again
MSequence.createTableSequence(Env.getCtx(), TableName, trxName, true);
m_sequence_id = CConnection.get().getDatabase().getNextID(TableName+"_SQ", trxName);
}
return m_sequence_id;
}
return MSequence.getNextID (AD_Client_ID, TableName, trxName); // it is ok to call deprecated method here
} // getNextID