diff --git a/db/ddlutils/oracle/procedures/nextID.sql b/db/ddlutils/oracle/procedures/nextID.sql index 2d23db2471..eda4003eff 100644 --- a/db/ddlutils/oracle/procedures/nextID.sql +++ b/db/ddlutils/oracle/procedures/nextID.sql @@ -24,11 +24,16 @@ BEGIN END; * ************************************************************************/ -AS +As +Isnativeseqon NVARCHAR2(1); +Tablename Nvarchar2(60); +sqlcmd VARCHAR2(200); BEGIN + + IF (p_System = 'Y') THEN SELECT CurrentNextSys - INTO o_NextID + INTO o_NextID FROM AD_Sequence WHERE AD_Sequence_ID=p_AD_Sequence_ID FOR UPDATE OF CurrentNextSys; @@ -36,16 +41,43 @@ BEGIN UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + IncrementNo WHERE AD_Sequence_ID=p_AD_Sequence_ID; - ELSE - SELECT CurrentNext - INTO o_NextID - FROM AD_Sequence - WHERE AD_Sequence_ID=p_AD_Sequence_ID - FOR UPDATE OF CurrentNext; - -- - UPDATE AD_Sequence - SET CurrentNext = CurrentNext + IncrementNo - WHERE AD_Sequence_ID=p_AD_Sequence_ID; + ELSE + + BEGIN + SELECT Value + Into Isnativeseqon + From Ad_Sysconfig + Where Name ='SYSTEM_NATIVE_SEQUENCE'; + EXCEPTION + WHEN NO_DATA_FOUND THEN + Isnativeseqon:= 'N'; + END; + + IF Isnativeseqon = 'Y' THEN + + Select Name + INTO tablename + From Ad_Sequence + Where Ad_Sequence_Id=P_Ad_Sequence_Id + And Istableid = 'Y'; + -- + Sqlcmd := 'SELECT '||Tablename||'_SQ.Nextval FROM DUAL'; + -- + Execute Immediate Sqlcmd Into O_Nextid; + -- + ELSE + + SELECT CurrentNext + INTO o_NextID + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID + FOR UPDATE OF CurrentNext; + -- + Update Ad_Sequence + Set Currentnext = Currentnext + Incrementno + Where Ad_Sequence_Id=P_Ad_Sequence_Id; + -- + END IF; END IF; -- EXCEPTION diff --git a/db/ddlutils/postgresql/functions/nextID.sql b/db/ddlutils/postgresql/functions/nextID.sql index 5f34795e32..a916ba4d2b 100644 --- a/db/ddlutils/postgresql/functions/nextID.sql +++ b/db/ddlutils/postgresql/functions/nextID.sql @@ -1,4 +1,4 @@ -CREATE OR REPLACE FUNCTION nextid( +CREATE OR REPLACE FUNCTION nextid( p_AD_Sequence_ID IN INTEGER, p_System IN VARCHAR, o_NextID OUT INTEGER @@ -21,7 +21,9 @@ CREATE OR REPLACE FUNCTION nextid( * select * from nextid((select ad_sequence_id from ad_sequence where name = 'Test')::Integer, 'Y'::Varchar); * ************************************************************************/ - +DECLARE +Isnativeseqon VARCHAR(1); +tablename VARCHAR(60); BEGIN IF (p_System = 'Y') THEN RAISE NOTICE 'system'; @@ -34,14 +36,35 @@ BEGIN SET CurrentNextSys = CurrentNextSys + IncrementNo WHERE AD_Sequence_ID=p_AD_Sequence_ID; ELSE - SELECT CurrentNext + + BEGIN + SELECT Value + INTO Isnativeseqon + FROM AD_SYSCONFIG + WHERE Name ='SYSTEM_NATIVE_SEQUENCE'; + EXCEPTION + WHEN NO_DATA_FOUND THEN + Isnativeseqon:= 'N'; + END; + + IF Isnativeseqon = 'Y' THEN + SELECT Name + INTO tablename + FROM Ad_Sequence + WHERE Ad_Sequence_Id=P_Ad_Sequence_Id; + -- + EXECUTE 'SELECT nextval('''||tablename||'_sq'''||')' INTO o_NextID; + -- + ELSE + SELECT CurrentNext INTO o_NextID - FROM AD_Sequence - WHERE AD_Sequence_ID=p_AD_Sequence_ID; - -- - UPDATE AD_Sequence - SET CurrentNext = CurrentNext + IncrementNo - WHERE AD_Sequence_ID=p_AD_Sequence_ID; + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + -- + UPDATE AD_Sequence + SET CurrentNext = CurrentNext + IncrementNo + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + END IF; END IF; -- EXCEPTION diff --git a/migration/360lts-release/oracle/921_IDEMPIERE-422_NativeSequence.sql b/migration/360lts-release/oracle/921_IDEMPIERE-422_NativeSequence.sql new file mode 100644 index 0000000000..01f75cab6e --- /dev/null +++ b/migration/360lts-release/oracle/921_IDEMPIERE-422_NativeSequence.sql @@ -0,0 +1,89 @@ +CREATE OR REPLACE PROCEDURE nextID +( + p_AD_Sequence_ID IN NUMBER, + p_System IN CHAR, + o_NextID OUT NUMBER +) +/************************************************************************* + * The contents of this file are subject to the Adempiere License. You may + * obtain a copy of the License at http://www.adempiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Adempiere ERP+CRM + * Copyright (C) 1999-2005 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: nextID.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Get Next ID - no Commit + * Description: + * Test via +DECLARE + v_NextID NUMBER; +BEGIN + nextID(2, 'Y', v_NextID); + DBMS_OUTPUT.PUT_LINE(v_NextID); +END; + * + ************************************************************************/ +As +Isnativeseqon NVARCHAR2(1); +Tablename Nvarchar2(60); +sqlcmd VARCHAR2(200); +BEGIN + + + IF (p_System = 'Y') THEN + SELECT CurrentNextSys + INTO o_NextID + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID + FOR UPDATE OF CurrentNextSys; + -- + UPDATE AD_Sequence + SET CurrentNextSys = CurrentNextSys + IncrementNo + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + ELSE + + BEGIN + SELECT Value + Into Isnativeseqon + From Ad_Sysconfig + Where Name ='SYSTEM_NATIVE_SEQUENCE'; + EXCEPTION + WHEN NO_DATA_FOUND THEN + Isnativeseqon:= 'N'; + END; + + IF Isnativeseqon = 'Y' THEN + + Select Name + INTO tablename + From Ad_Sequence + Where Ad_Sequence_Id=P_Ad_Sequence_Id + And Istableid = 'Y'; + -- + Sqlcmd := 'SELECT '||Tablename||'_SQ.Nextval FROM DUAL'; + -- + Execute Immediate Sqlcmd Into O_Nextid; + -- + ELSE + + SELECT CurrentNext + INTO o_NextID + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID + FOR UPDATE OF CurrentNext; + -- + Update Ad_Sequence + Set Currentnext = Currentnext + Incrementno + Where Ad_Sequence_Id=P_Ad_Sequence_Id; + -- + END IF; + END IF; + -- +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE(SQLERRM); +END nextID; +/ +SELECT register_migration_script('921_IDEMPIERE-422_NativeSequence.sql') FROM dual; + diff --git a/migration/360lts-release/postgresql/921_IDEMPIERE-422_NativeSequence.sql b/migration/360lts-release/postgresql/921_IDEMPIERE-422_NativeSequence.sql new file mode 100644 index 0000000000..2a47b95d44 --- /dev/null +++ b/migration/360lts-release/postgresql/921_IDEMPIERE-422_NativeSequence.sql @@ -0,0 +1,78 @@ +CREATE OR REPLACE FUNCTION nextid( + p_AD_Sequence_ID IN INTEGER, + p_System IN VARCHAR, + o_NextID OUT INTEGER +) + RETURNS INTEGER AS $body$ +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2005 Jorg Janke, ComPiere, Inc. All Rights Reserved. + * + * converted to postgreSQL by Karsten Thiemann (Schaeffer AG), + * kthiemann@adempiere.org + ************************************************************************* + *** + * Title: Get Next ID - no Commit + * Description: Returns the next id of the sequence. + * Test: + * select * from nextid((select ad_sequence_id from ad_sequence where name = 'Test')::Integer, 'Y'::Varchar); + * + ************************************************************************/ +DECLARE +Isnativeseqon VARCHAR(1); +tablename VARCHAR(60); +BEGIN + IF (p_System = 'Y') THEN + RAISE NOTICE 'system'; + SELECT CurrentNextSys + INTO o_NextID + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + -- + UPDATE AD_Sequence + SET CurrentNextSys = CurrentNextSys + IncrementNo + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + ELSE + + BEGIN + SELECT Value + INTO Isnativeseqon + FROM AD_SYSCONFIG + WHERE Name ='SYSTEM_NATIVE_SEQUENCE'; + EXCEPTION + WHEN NO_DATA_FOUND THEN + Isnativeseqon:= 'N'; + END; + + IF Isnativeseqon = 'Y' THEN + SELECT Name + INTO tablename + FROM Ad_Sequence + WHERE Ad_Sequence_Id=P_Ad_Sequence_Id; + -- + EXECUTE 'SELECT nextval('''||tablename||'_sq'''||')' INTO o_NextID; + -- + ELSE + SELECT CurrentNext + INTO o_NextID + FROM AD_Sequence + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + -- + UPDATE AD_Sequence + SET CurrentNext = CurrentNext + IncrementNo + WHERE AD_Sequence_ID=p_AD_Sequence_ID; + END IF; + END IF; + -- +EXCEPTION + WHEN OTHERS THEN + RAISE NOTICE '%',SQLERRM; +END; +$body$ LANGUAGE plpgsql; + +SELECT register_migration_script('921_IDEMPIERE-422_NativeSequence.sql') FROM dual +; + diff --git a/migration/processes_post_migration/oracle/03_update_sequences.sql b/migration/processes_post_migration/oracle/03_update_sequences.sql index ac1abdfa3a..4ba7274544 100644 --- a/migration/processes_post_migration/oracle/03_update_sequences.sql +++ b/migration/processes_post_migration/oracle/03_update_sequences.sql @@ -7,7 +7,9 @@ DECLARE currentnextsys NUMBER (10); currentnext NUMBER (10); currentseqsys NUMBER (10); - currentseq NUMBER (10); + Currentseq Number (10); + Isnativeseqon Varchar2(1); + sqlcmd VARCHAR2(200); BEGIN DBMS_OUTPUT.PUT_LINE ('Start'); @@ -38,8 +40,18 @@ BEGIN DBMS_OUTPUT.PUT_LINE ('Table not found'); DBMS_OUTPUT.PUT_LINE (cmdsys); GOTO next_iteration; - END; - + End; + + BEGIN + SELECT Value + Into Isnativeseqon + From Ad_Sysconfig + Where Name ='SYSTEM_NATIVE_SEQUENCE'; + Exception + When NO_DATA_FOUND Then + Isnativeseqon :='N'; + End; + IF currentnextsys IS NULL THEN currentnextsys := 0; @@ -76,16 +88,26 @@ BEGIN INTO currentnext FROM DUAL; - cmdseq := - 'SELECT currentnext, currentnextsys FROM AD_Sequence ' + If Isnativeseqon ='Y' Then + Cmdseq := + 'SELECT '||R.Tablename||'_SQ.Nextval as currentnext, + currentnextsys + FROM AD_Sequence ' || 'WHERE Name = ''' - || r.tablename - || ''' AND istableid = ''Y'''; + || r.Tablename + || ''' AND istableid = ''Y'''; + ELSE + cmdseq := + 'SELECT currentnext, currentnextsys FROM AD_Sequence ' + || 'WHERE Name = ''' + || r.tablename + || ''' AND istableid = ''Y'''; + END IF; EXECUTE IMMEDIATE cmdseq INTO currentseq, currentseqsys; - IF currentnextsys <> currentseqsys OR currentnext <> currentseq + IF currentnextsys <> currentseqsys OR (currentnext <> currentseq AND Isnativeseqon ='N') THEN DBMS_OUTPUT.PUT_LINE ( r.tablename || ' sys=' @@ -108,8 +130,16 @@ BEGIN DBMS_OUTPUT.PUT_LINE (cmdupd); EXECUTE IMMEDIATE cmdupd; - END IF; - + End If; + + If Currentseq < Currentnext And Isnativeseqon ='Y' Then + Sqlcmd := 'SELECT '||R.Tablename||'_SQ.Nextval FROM DUAL'; + DBMS_OUTPUT.PUT_LINE (Sqlcmd); + While Not Currentseq >= (currentnext-1) Loop + Execute Immediate Sqlcmd + Into currentseq; + End Loop; + END IF; <> NULL; END LOOP; diff --git a/migration/processes_post_migration/postgresql/03_update_sequences.sql b/migration/processes_post_migration/postgresql/03_update_sequences.sql index 04453fadcd..4380cea0de 100644 --- a/migration/processes_post_migration/postgresql/03_update_sequences.sql +++ b/migration/processes_post_migration/postgresql/03_update_sequences.sql @@ -1,4 +1,4 @@ -CREATE OR REPLACE FUNCTION update_sequences() RETURNS void as $func$ +CREATE OR REPLACE FUNCTION update_sequences() RETURNS void as $func$ -- TODO: Currently not inserting new sequences DECLARE cmdsys VARCHAR (1000); @@ -11,10 +11,11 @@ DECLARE currentseq NUMERIC (10); ok BOOLEAN; r RECORD; + isnativeseqon VARCHAR (1); BEGIN - FOR r IN (SELECT tablename - FROM AD_TABLE t + FOR r IN (SELECT tablename + FROM AD_TABLE t WHERE EXISTS ( SELECT 1 FROM AD_COLUMN c @@ -41,6 +42,17 @@ BEGIN END; IF ok THEN + + BEGIN + SELECT Value + INTO isnativeseqon + FROM AD_SYSCONFIG + WHERE Name ='SYSTEM_NATIVE_SEQUENCE'; + EXCEPTION + WHEN NO_DATA_FOUND THEN + isnativeseqon:= 'N'; + END; + IF currentnextsys IS NULL THEN currentnextsys := 0; @@ -72,15 +84,25 @@ BEGIN ELSE coalesce (currentnext + 1, 1000000) END ; - cmdseq := - 'SELECT currentnext, currentnextsys FROM AD_Sequence ' - || 'WHERE Name = ''' - || r.tablename - || ''' AND istableid = ''Y'''; + IF isnativeseqon ='Y' THEN + cmdseq := + 'SELECT nextval('''||trim(r.tablename)||'_sq'''||') as currentnext, + currentnextsys + FROM AD_Sequence ' + || 'WHERE Name = ''' + || r.tablename + || ''' AND istableid = ''Y'''; + ELSE + cmdseq := + 'SELECT currentnext, currentnextsys FROM AD_Sequence ' + || 'WHERE Name = ''' + || r.tablename + || ''' AND istableid = ''Y'''; + END IF; EXECUTE cmdseq INTO currentseq, currentseqsys; - IF currentnextsys <> currentseqsys OR currentnext <> currentseq + IF currentnextsys <> currentseqsys OR (currentnext <> currentseq AND isnativeseqon ='N') THEN cmdupd := 'update ad_sequence set currentnextsys = ' @@ -93,8 +115,14 @@ BEGIN EXECUTE cmdupd; END IF; + IF currentseq < currentnext AND isnativeseqon ='Y' THEN + --RAISE NOTICE 'currentseq % ,currentnext %',currentseq,currentnext; + WHILE NOT currentseq >= (currentnext-1) LOOP + EXECUTE 'SELECT nextval('''||trim(r.tablename)||'_sq'''||')' INTO currentseq; + --RAISE NOTICE 'currentseq % ,currentnext %',currentseq,currentnext; + END LOOP; + END IF; END IF; - END LOOP; END; $func$ LANGUAGE plpgsql; diff --git a/org.adempiere.base.process/src/org/compiere/process/SequenceCheck.java b/org.adempiere.base.process/src/org/compiere/process/SequenceCheck.java index 3b07a60af3..a73dc0d99a 100644 --- a/org.adempiere.base.process/src/org/compiere/process/SequenceCheck.java +++ b/org.adempiere.base.process/src/org/compiere/process/SequenceCheck.java @@ -202,42 +202,28 @@ public class SequenceCheck extends SvrProcess + "ORDER BY Name"; int counter = 0; PreparedStatement pstmt = null; + ResultSet rs = null; String trxName = null; if (sp != null) trxName = sp.get_TrxName(); try { pstmt = DB.prepareStatement(sql, trxName); - ResultSet rs = pstmt.executeQuery(); + rs = pstmt.executeQuery(); while (rs.next()) { MSequence seq = new MSequence (ctx, rs, trxName); - int old = seq.getCurrentNext(); - int oldSys = seq.getCurrentNextSys(); - if (seq.validateTableIDValue()) - { - if (seq.getCurrentNext() != old) - { - StringBuilder msg = new StringBuilder(seq.getName()).append(" ID ") - .append(old).append(" -> ").append(seq.getCurrentNext()); - if (sp != null) - sp.addLog(0, null, null, msg.toString()); - else - s_log.fine(msg.toString()); - } - if (seq.getCurrentNextSys() != oldSys) - { - StringBuilder msg = new StringBuilder(seq.getName()).append(" Sys ") - .append(oldSys).append(" -> ").append(seq.getCurrentNextSys()); - if (sp != null) - sp.addLog(0, null, null, msg.toString()); - else - s_log.fine(msg.toString()); - } - if (seq.save()) - counter++; + String tableValidation= seq.validateTableIDValue(); + if (tableValidation!=null){ + if (sp != null) + sp.addLog(0, null, null, tableValidation); else - s_log.severe("Not updated: " + seq); + s_log.fine(tableValidation); + + if (seq.save()) + counter++; + else + s_log.severe("Not updated: " + seq); } // else if (CLogMgt.isLevel(6)) // log.fine("checkTableID - skipped " + tableName); @@ -249,16 +235,10 @@ public class SequenceCheck extends SvrProcess catch (Exception e) { s_log.log(Level.SEVERE, sql, e); - } - try + }finally { - if (pstmt != null) - pstmt.close(); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; + DB.close(rs, pstmt); + rs = null; pstmt = null; } s_log.fine("#" + counter); } // checkTableID diff --git a/org.adempiere.base/src/org/compiere/model/MSequence.java b/org.adempiere.base/src/org/compiere/model/MSequence.java index 1092822971..75c62d7201 100644 --- a/org.adempiere.base/src/org/compiere/model/MSequence.java +++ b/org.adempiere.base/src/org/compiere/model/MSequence.java @@ -62,7 +62,8 @@ public class MSequence extends X_AD_Sequence private static final int QUERY_TIME_OUT = 30; private static final String NoYearNorMonth = "-"; - + + @Deprecated public static int getNextID (int AD_Client_ID, String TableName) { return getNextID(AD_Client_ID, TableName, null); @@ -74,8 +75,13 @@ public class MSequence extends X_AD_Sequence * @param AD_Client_ID client * @param TableName table name * @param trxName deprecated. - * @return next no or (-1=not found, -2=error) - */ + * @return next no or (-1=not found, -2=error) + * + * WARNING!! This method doesn't take into account the native sequence setting, it always read from table AD_Sequence + * must be used JUST for the method Enable Native Sequence + * + * @deprecated + */ public static int getNextID (int AD_Client_ID, String TableName, String trxName) { if (TableName == null || TableName.length() == 0) @@ -693,7 +699,7 @@ public class MSequence extends X_AD_Sequence seq.setDescription("Table " + TableName); seq.setIsTableID(tableID); seq.saveEx(); - next_id = seq.getCurrentNext(); + next_id = INIT_NO; } if (! CConnection.get().getDatabase().createSequence(TableName+"_SQ", 1, 0 , 99999999, next_id, trxName)) return false; @@ -883,10 +889,10 @@ public class MSequence extends X_AD_Sequence * Validate Table Sequence Values * @return true if updated */ - public boolean validateTableIDValue() + public String validateTableIDValue() { if (!isTableID()) - return false; + return null; String tableName = getName(); int AD_Column_ID = DB.getSQLValue(null, "SELECT MAX(c.AD_Column_ID) " + "FROM AD_Table t" @@ -894,13 +900,14 @@ public class MSequence extends X_AD_Sequence + "WHERE t.TableName='" + tableName + "'" + " AND c.ColumnName='" + tableName + "_ID'"); if (AD_Column_ID <= 0) - return false; + return null; // MSystem system = MSystem.get(getCtx()); int IDRangeEnd = 0; if (system.getIDRangeEnd() != null) IDRangeEnd = system.getIDRangeEnd().intValue(); - boolean change = false; + + String changeMsg = null; String info = null; // Current Next @@ -910,12 +917,14 @@ public class MSequence extends X_AD_Sequence int maxTableID = DB.getSQLValue(null, sql); if (maxTableID < INIT_NO) maxTableID = INIT_NO - 1; - maxTableID++; // Next - if (getCurrentNext() < maxTableID) + maxTableID++; // Next + + int currentNextValue = getCurrentNext(); + if (currentNextValue < maxTableID) { setCurrentNext(maxTableID); info = "CurrentNext=" + maxTableID; - change = true; + changeMsg = getName() + " ID " + currentNextValue + " -> " + maxTableID; } // Get Max System_ID used in Table @@ -924,22 +933,44 @@ public class MSequence extends X_AD_Sequence int maxTableSysID = DB.getSQLValue(null, sql); if (maxTableSysID <= 0) maxTableSysID = INIT_SYS_NO - 1; - maxTableSysID++; // Next - if (getCurrentNextSys() < maxTableSysID) - { + int currentNextSysValue = getCurrentNextSys(); + if (currentNextSysValue < maxTableSysID){ setCurrentNextSys(maxTableSysID); if (info == null) info = "CurrentNextSys=" + maxTableSysID; else info += " - CurrentNextSys=" + maxTableSysID; - change = true; + + if (changeMsg == null) + changeMsg = getName() + " Sys " + currentNextSysValue + " -> " + maxTableSysID; + else + changeMsg += " - " +getName() + " Sys " + currentNextSysValue + " -> " + maxTableSysID; } if (info != null) - log.fine(getName() + " - " + info); - return change; + log.fine(getName() + " - " + info); + + return changeMsg; } // validate - + @Override + public int getCurrentNext() { + if (MSysConfig.getBooleanValue(MSysConfig.SYSTEM_NATIVE_SEQUENCE,false) && isTableID()){ + return DB.getNextID (getAD_Client_ID(),getName(),get_TrxName()); + }else { + return super.getCurrentNext(); + } + } + + @Override + public void setCurrentNext(int CurrentNext) { + if (MSysConfig.getBooleanValue(MSysConfig.SYSTEM_NATIVE_SEQUENCE,false) && isTableID()){ + while (DB.getNextID(getAD_Client_ID(),getName(),get_TrxName()) < (CurrentNext-1)) { + // do nothing - the while is incrementing the sequence + } + }else { + super.setCurrentNext(CurrentNext); + } + } /************************************************************************** * Test * @param args ignored