Skip to content

Commit

Permalink
Avoid using Postgres OID (#10208)
Browse files Browse the repository at this point in the history
* fix QuerySelectionToDeleteHelper

stack trace was:

org.adempiere.exceptions.DBException: ERROR: column "oid" does not exist
  Position: 259
Additional parameters:
 I_C_Queue_WorkPackage: X_C_Queue_WorkPackage[C_Queue_WorkPackage_ID=1000941, trxName=null]
 IQueueProcessor: ThreadPoolQueueProcessor{name=FactAcctLogWorkpackageProcessor, executor=BlockingExecutorWrapper(semaphore=java.util.concurrent.Semaphore@33050aae[Permits = 0], delegate=java.util.concurrent.ThreadPoolExecutor@4c5ed220[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 46], logger=Logger[org.adempiere.util.concurrent.BlockingExecutorWrapper])}
 trxName: <<ThreadInherited>>
	SQL: UPDATE Fact_Acct_Log t
 SET ProcessingTag=?
 FROM (
 SELECT Action,AD_Client_ID,AD_Org_ID,AmtAcctCr,AmtAcctDr,C_AcctSchema_ID,C_ElementValue_ID,C_Period_ID,Created,CreatedBy,DateAcct,Fact_Acct_ID,IsActive,PostingType,ProcessingTag,Qty,Updated,UpdatedBy
 , oid as ZZ_RowId  FROM Fact_Acct_Log
 WHERE ((ProcessingTag IS NULL))
 LIMIT 500  OFFSET 0) f
 WHERE t.oid = f.ZZ_RowId
	SQL params: [6ac227c0-6225-4199-84b3-ec93158253de]
	at org.adempiere.exceptions.DBException.wrapIfNeeded(DBException.java:92)
	at org.compiere.util.DB.executeUpdate(DB.java:948)
	at org.compiere.util.DB.executeUpdateEx(DB.java:994)
	at org.compiere.util.DB.executeUpdateEx(DB.java:979)
	at org.adempiere.ad.dao.impl.TypedSqlQuery.updateSql_UsingSelectFromSubQuery(TypedSqlQuery.java:1853)
	at org.adempiere.ad.dao.impl.TypedSqlQuery.updateSql(TypedSqlQuery.java:1777)
	at org.adempiere.ad.dao.impl.TypedSqlQuery.updateDirectly(TypedSqlQuery.java:1733)
	at org.adempiere.ad.dao.impl.CompositeQueryUpdaterExecutor.execute(CompositeQueryUpdaterExecutor.java:51)
	at de.metas.acct.aggregation.impl.FactAcctLogDAO.updateProcessingTag(FactAcctLogDAO.java:87)
	at de.metas.acct.aggregation.impl.FactAcctLogDAO.tagAndRetrieve(FactAcctLogDAO.java:68)
	at de.metas.acct.aggregation.impl.FactAcctLogBL$1.run(FactAcctLogBL.java:65)
	at org.adempiere.ad.trx.api.impl.TrxCallableWrappers$3.call(TrxCallableWrappers.java:147)
	at org.adempiere.ad.trx.api.impl.TrxCallableWrappers$3.call(TrxCallableWrappers.java:137)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call0(AbstractTrxManager.java:753)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call(AbstractTrxManager.java:666)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call(AbstractTrxManager.java:567)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call(AbstractTrxManager.java:498)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.callInNewTrx(AbstractTrxManager.java:476)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.runInNewTrx(AbstractTrxManager.java:470)
	at de.metas.acct.aggregation.impl.FactAcctLogBL.processAll(FactAcctLogBL.java:59)
	at de.metas.acct.aggregation.async.FactAcctLogWorkpackageProcessor.processWorkPackage(FactAcctLogWorkpackageProcessor.java:69)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.invokeProcessorAndHandleException(WorkpackageProcessorTask.java:336)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.processWorkpackage(WorkpackageProcessorTask.java:328)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.lambda$run0$1(WorkpackageProcessorTask.java:199)
	at org.adempiere.ad.trx.api.impl.TrxCallableWrappers$2.call(TrxCallableWrappers.java:105)
	at org.adempiere.ad.trx.api.impl.TrxCallableWrappers$2.call(TrxCallableWrappers.java:95)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call0(AbstractTrxManager.java:753)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.call(AbstractTrxManager.java:666)
	at org.adempiere.ad.trx.api.impl.AbstractTrxManager.run(AbstractTrxManager.java:574)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.run0(WorkpackageProcessorTask.java:193)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.lambda$run$0(WorkpackageProcessorTask.java:158)
	at de.metas.monitoring.adapter.PerformanceMonitoringService.lambda$monitorTransaction$1(PerformanceMonitoringService.java:83)
	at de.metas.monitoring.adapter.apm.APMPerformanceMonitoringService.monitorTransaction(APMPerformanceMonitoringService.java:64)
	at de.metas.monitoring.adapter.PerformanceMonitoringService.monitorTransaction(PerformanceMonitoringService.java:81)
	at de.metas.async.processor.impl.WorkpackageProcessorTask.run(WorkpackageProcessorTask.java:157)
	at org.adempiere.util.concurrent.BlockingExecutorWrapper$1.run(BlockingExecutorWrapper.java:90)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.postgresql.util.PSQLException: ERROR: column "oid" does not exist
  Position: 259
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2505)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2241)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:310)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:447)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:368)
	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:158)
	at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:124)
	at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:1502)
	at org.adempiere.sql.impl.CPreparedStatementProxy.executeUpdate(CPreparedStatementProxy.java:138)
	at org.compiere.util.DB.executeUpdate(DB.java:879)
	... 37 common frames omitted

* get rid of AdempiereDatabase.getRowIdSql() because we no longer support OIDs

Currently it was used to UPDATE directly following tables
* T_Query_Selection_ToDelete - which i've fixed in previous commit
* C_SubscriptionProgress
* PP_MRP
* C_Invoice_Line_Alloc
* C_Invoice_Candidate
* M_ReceiptSchedule
* M_ShipmentSchedule

all of those tables have sigle primary key

* add Fact_Fact_Log.Fact_Fact_Log_ID
  • Loading branch information
teosarca committed Nov 11, 2020
1 parent 646af83 commit dcdfa1e
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- 2020-11-10T21:59:23.163Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
INSERT INTO AD_Element (AD_Client_ID,AD_Element_ID,AD_Org_ID,ColumnName,Created,CreatedBy,EntityType,IsActive,Name,PrintName,Updated,UpdatedBy) VALUES (0,578538,0,'Fact_Acct_Log_ID',TO_TIMESTAMP('2020-11-10 23:59:22','YYYY-MM-DD HH24:MI:SS'),100,'de.metas.acct','Y','Fact Acct change log table','Fact Acct change log table',TO_TIMESTAMP('2020-11-10 23:59:22','YYYY-MM-DD HH24:MI:SS'),100)
;

-- 2020-11-10T21:59:23.167Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
INSERT INTO AD_Element_Trl (AD_Language,AD_Element_ID, CommitWarning,Description,Help,Name,PO_Description,PO_Help,PO_Name,PO_PrintName,PrintName,WEBUI_NameBrowse,WEBUI_NameNew,WEBUI_NameNewBreadcrumb, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language, t.AD_Element_ID, t.CommitWarning,t.Description,t.Help,t.Name,t.PO_Description,t.PO_Help,t.PO_Name,t.PO_PrintName,t.PrintName,t.WEBUI_NameBrowse,t.WEBUI_NameNew,t.WEBUI_NameNewBreadcrumb, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Element t WHERE l.IsActive='Y'AND (l.IsSystemLanguage='Y' OR l.IsBaseLanguage='Y') AND t.AD_Element_ID=578538 AND NOT EXISTS (SELECT 1 FROM AD_Element_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Element_ID=t.AD_Element_ID)
;

-- 2020-11-10T21:59:23.411Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
INSERT INTO AD_Column (AD_Client_ID,AD_Column_ID,AD_Element_ID,AD_Org_ID,AD_Reference_ID,AD_Table_ID,ColumnName,Created,CreatedBy,EntityType,FieldLength,IsActive,IsAllowLogging,IsAlwaysUpdateable,IsEncrypted,IsIdentifier,IsKey,IsMandatory,IsParent,IsSelectionColumn,IsTranslated,IsUpdateable,Name,Updated,UpdatedBy,Version) VALUES (0,572084,578538,0,13,540695,'Fact_Acct_Log_ID',TO_TIMESTAMP('2020-11-10 23:59:22','YYYY-MM-DD HH24:MI:SS'),100,'de.metas.acct',10,'Y','Y','N','N','N','Y','Y','N','N','N','N','Fact Acct change log table',TO_TIMESTAMP('2020-11-10 23:59:22','YYYY-MM-DD HH24:MI:SS'),100,1)
;

-- 2020-11-10T21:59:23.414Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
INSERT INTO AD_Column_Trl (AD_Language,AD_Column_ID, Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language, t.AD_Column_ID, t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Column t WHERE l.IsActive='Y'AND (l.IsSystemLanguage='Y') AND t.AD_Column_ID=572084 AND NOT EXISTS (SELECT 1 FROM AD_Column_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Column_ID=t.AD_Column_ID)
;

-- 2020-11-10T21:59:23.488Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
/* DDL */ select update_Column_Translation_From_AD_Element(578538)
;

-- 2020-11-10T21:59:23.507Z
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
ALTER SEQUENCE FACT_ACCT_LOG_SEQ INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 RESTART 1000000
;

ALTER TABLE Fact_Acct_Log
ADD COLUMN Fact_Acct_Log_ID numeric(10, 0)
DEFAULT nextval('fact_acct_log_seq')
NOT NULL
;

ALTER TABLE fact_acct_log ADD CONSTRAINT fact_acct_log_pkey PRIMARY KEY (fact_acct_log_id);

Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,7 @@ public Object clone()
/**
* Inserts the query result into a <code>T_Selection</code> for the given AD_PInstance_ID
*
* @param AD_PInstance_ID
* @param pinstanceId
* @return number of records inserted in selection
*/
@Override
Expand Down Expand Up @@ -1811,11 +1811,10 @@ private final int updateSql_UsingSelectFromSubQuery(final ISqlQueryUpdater<T> sq
// Get the key column name / row id
final String tableName = getTableName();
final POInfo info = getPOInfo();
String keyColumnName = info.getKeyColumnName();
final String keyColumnName = info.getKeyColumnName();
if (keyColumnName == null)
{
// Fallback if table has no primary key: use database specific ROW ID
keyColumnName = DB.getDatabase().getRowIdSql(tableName);
throw new AdempiereException("Cannot update table `" + tableName + "`directly because it does not have a single primary key defined");
}

final List<Object> sqlParams = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,4 @@ public interface AdempiereDatabase
* are already exception handling and just want to use this method to get whatever info you can (and not to throw yet another exception).
*/
String getConnectionBackendId(Connection connection, boolean throwDBException);

/**
* @return SQL code for getting the ROW ID of a given table.
*/
String getRowIdSql(final String tableName);
} // AdempiereDatabase
Original file line number Diff line number Diff line change
Expand Up @@ -1047,14 +1047,6 @@ public String getConnectionBackendId(final Connection connection, final boolean
return String.valueOf(pgBackendPID);
}

/** @deprecated OIDs are deprecated in PostgreSQL */
@Deprecated
@Override
public String getRowIdSql(final String tableName)
{
return "oid";
}

private static List<String> getAquiredConnectionInfos(final ComboPooledDataSource dataSource) throws Exception
{
final List<String> infos = BasicResourcePool_MetasfreshObserver.getAquiredConnectionInfos(dataSource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
import de.metas.util.lang.UIDStringUtil;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import org.adempiere.ad.dao.ICompositeQueryUpdater;
import org.adempiere.ad.dao.IQueryBL;
import org.adempiere.ad.trx.api.ITrx;
import org.adempiere.ad.trx.api.ITrxListenerManager.TrxEventTiming;
import org.adempiere.ad.trx.api.ITrxManager;
import org.adempiere.model.PlainContextAware;
import org.compiere.model.IQuery;
import org.compiere.util.DB;
import org.slf4j.Logger;
Expand Down Expand Up @@ -78,7 +76,9 @@ public static void scheduleDeleteSelections(final Set<String> uuids, final Strin
.registerHandlingMethod(trx -> scheduleDeleteSelectionsNow(uuids));
}

/** Inserts the uuids in a hardcoded way, with one DB statement per 1000 uuids */
/**
* Inserts the uuids in a hardcoded way, with one DB statement per 1000 uuids
*/
private static void scheduleDeleteSelectionsNow(@NonNull final Set<String> uuids)
{
if (uuids.isEmpty())
Expand Down Expand Up @@ -133,7 +133,7 @@ public static void deleteScheduledSelectionsNoFail()

/**
* Processes one {@code T_Query_Selection_ToDelete} record at a time, until all are done.
*
* <p>
* Each {@code T_Query_Selection_ToDelete} is done it its own DB-transaction.
* We run in those small steps to make sure each individual transaction is finished within the connection pool's timeout.
*/
Expand All @@ -142,38 +142,41 @@ public static void deleteScheduledSelections()
final ITrxManager trxManager = Services.get(ITrxManager.class);
final int maxQuerySelectionToDeleteToProcess = 1;

int lastQuerySelectionDeletedCount = Integer.MAX_VALUE;
while (lastQuerySelectionDeletedCount > 0)
boolean tryRemove = true;
while (tryRemove)
{
lastQuerySelectionDeletedCount = trxManager.callInNewTrx(() -> deleteScheduledSelections0(maxQuerySelectionToDeleteToProcess));
logger.debug("Last invocation of deleteScheduledSelections0 returned lastQuerySelectionDeletedCount={}", lastQuerySelectionDeletedCount);
final boolean removedSomething = trxManager.callInNewTrx(() -> deleteScheduledSelections0(maxQuerySelectionToDeleteToProcess));
logger.debug("Last invocation of deleteScheduledSelections0 returned removedSomething+{}", removedSomething);

tryRemove = removedSomething;
}
}

private static int deleteScheduledSelections0(final int maxQuerySelectionToDeleteToProcess)
private static boolean deleteScheduledSelections0(final int maxQuerySelectionToDeleteToProcess)
{
final IQueryBL queryBL = Services.get(IQueryBL.class);
final PlainContextAware inheritedTrx = PlainContextAware.newWithThreadInheritedTrx();

// Tag scheduled IDs
final String executorId = UIDStringUtil.createRandomUUID();
final ICompositeQueryUpdater<I_T_Query_Selection_ToDelete> updater = queryBL
.createCompositeQueryUpdater(I_T_Query_Selection_ToDelete.class)
.addSetColumnValue(I_T_Query_Selection_ToDelete.COLUMNNAME_Executor_UUID, executorId);

final int querySelectionToDeleteCount = queryBL
.createQueryBuilder(I_T_Query_Selection_ToDelete.class, inheritedTrx)
.addEqualsFilter(I_T_Query_Selection_ToDelete.COLUMNNAME_Executor_UUID, null).setLimit(maxQuerySelectionToDeleteToProcess)
.create()
.updateDirectly(updater);
logger.debug("Tagged {} selectionIds to be deleted", querySelectionToDeleteCount);
if (querySelectionToDeleteCount <= 0)

// Tag scheduled IDs
{
return querySelectionToDeleteCount;
final String sql = "UPDATE " + I_T_Query_Selection_ToDelete.Table_Name + " t"
+ " SET Executor_UUID=?"
+ " WHERE"
+ " UUID IN (SELECT distinct UUID FROM T_Query_Selection_ToDelete WHERE Executor_UUID IS NULL LIMIT ?)";

final int querySelectionToDeleteCount = DB.executeUpdateEx(sql,
new Object[] { executorId, maxQuerySelectionToDeleteToProcess },
ITrx.TRXNAME_ThreadInherited);
logger.debug("Tagged {} selectionIds to be deleted", querySelectionToDeleteCount);
if (querySelectionToDeleteCount <= 0)
{
return false;
}
}

final IQuery<I_T_Query_Selection_ToDelete> selectionToDeleteQuery = queryBL
.createQueryBuilder(I_T_Query_Selection_ToDelete.class, inheritedTrx)
.createQueryBuilder(I_T_Query_Selection_ToDelete.class)
.addEqualsFilter(I_T_Query_Selection_ToDelete.COLUMNNAME_Executor_UUID, executorId)
.create();

Expand Down Expand Up @@ -206,6 +209,7 @@ private static int deleteScheduledSelections0(final int maxQuerySelectionToDelet
final int count = selectionToDeleteQuery.deleteDirectly();
logger.debug("Deleted {} rows from {}", count, I_T_Query_Selection_ToDelete.Table_Name);
}
return querySelectionToDeleteCount;

return true;
}
}

0 comments on commit dcdfa1e

Please sign in to comment.