From c3ff463ee333e66869fba44925fec583d710c41b Mon Sep 17 00:00:00 2001 From: Teo Sarca Date: Sat, 29 Apr 2017 13:13:05 +0300 Subject: [PATCH] move code from SqlViewBinding to SqlViewRepository; remove Attributes https://github.com/metasfresh/metasfresh-webui-api/issues/330 --- .../ui/web/view/SqlViewEvaluationCtx.java | 5 + .../metas/ui/web/view/SqlViewRepository.java | 55 ++++-- .../java/de/metas/ui/web/view/ViewRow.java | 51 +---- .../web/view/descriptor/SqlViewBinding.java | 179 +++++++----------- .../SqlViewRowIdsOrderedSelectionFactory.java | 4 +- 5 files changed, 134 insertions(+), 160 deletions(-) diff --git a/src/main/java/de/metas/ui/web/view/SqlViewEvaluationCtx.java b/src/main/java/de/metas/ui/web/view/SqlViewEvaluationCtx.java index b05fb71e6..dca921a2b 100644 --- a/src/main/java/de/metas/ui/web/view/SqlViewEvaluationCtx.java +++ b/src/main/java/de/metas/ui/web/view/SqlViewEvaluationCtx.java @@ -62,6 +62,11 @@ public String toString() .add("permissionsKey", permissionsKey) .toString(); } + + public UserRolePermissionsKey getPermissionsKey() + { + return permissionsKey; + } public Evaluatee toEvaluatee() { diff --git a/src/main/java/de/metas/ui/web/view/SqlViewRepository.java b/src/main/java/de/metas/ui/web/view/SqlViewRepository.java index ebcd1f922..160693b3e 100644 --- a/src/main/java/de/metas/ui/web/view/SqlViewRepository.java +++ b/src/main/java/de/metas/ui/web/view/SqlViewRepository.java @@ -3,18 +3,26 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import org.adempiere.ad.expression.api.IExpressionEvaluator.OnVariableNotFound; +import org.adempiere.ad.security.IUserRolePermissions; +import org.adempiere.ad.security.IUserRolePermissionsDAO; +import org.adempiere.ad.security.UserRolePermissionsKey; +import org.adempiere.ad.security.permissions.WindowMaxQueryRecordsConstraint; import org.adempiere.ad.trx.api.ITrx; import org.adempiere.exceptions.DBException; import org.adempiere.util.Check; +import org.adempiere.util.Services; import org.compiere.util.DB; import org.compiere.util.Evaluatee; import org.slf4j.Logger; import com.google.common.base.MoreObjects; +import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; import de.metas.logging.LogManager; @@ -22,6 +30,7 @@ import de.metas.ui.web.view.descriptor.SqlViewBinding; import de.metas.ui.web.view.descriptor.SqlViewRowFieldBinding; import de.metas.ui.web.view.descriptor.SqlViewRowFieldBinding.SqlViewRowFieldLoader; +import de.metas.ui.web.view.descriptor.SqlViewRowIdsOrderedSelectionFactory; import de.metas.ui.web.window.datatypes.DocumentId; import de.metas.ui.web.window.datatypes.WindowId; import de.metas.ui.web.window.model.filters.DocumentFilter; @@ -76,21 +85,48 @@ public String getSqlWhereClause(final ViewId viewId, final Collection sqlOrderBysByFieldName = sqlBindings.getSqlOrderBysIndexedByFieldName(viewEvalCtx); + return new SqlViewRowIdsOrderedSelectionFactory(sqlCreateFromViewId, sqlOrderBysByFieldName); } public ViewRowIdsOrderedSelection createOrderedSelection(final SqlViewEvaluationCtx viewEvalCtx, final WindowId windowId, final List filters) { - return sqlBindings.createOrderedSelection(viewEvalCtx, windowId, filters); + final ViewId viewId = ViewId.random(windowId); + + final UserRolePermissionsKey permissionsKey = viewEvalCtx.getPermissionsKey(); + final IUserRolePermissions permissions = Services.get(IUserRolePermissionsDAO.class).retrieveUserRolePermissions(permissionsKey); + final int queryLimit = permissions.getConstraint(WindowMaxQueryRecordsConstraint.class) + .or(WindowMaxQueryRecordsConstraint.DEFAULT) + .getMaxQueryRecordsPerRole(); + + // + // + final List sqlParams = new ArrayList<>(); + final String sql = sqlBindings.getSqlCreateSelectionFrom(sqlParams, viewEvalCtx, viewId, filters, queryLimit); + + // + // Execute it, so we insert in our T_WEBUI_ViewSelection + final Stopwatch stopwatch = Stopwatch.createStarted(); + final long rowsCount = DB.executeUpdateEx(sql, sqlParams.toArray(), ITrx.TRXNAME_ThreadInherited); + stopwatch.stop(); + final boolean queryLimitHit = queryLimit > 0 && rowsCount >= queryLimit; + logger.trace("Created selection {}, rowsCount={}, duration={} \n SQL: {} -- {}", viewId, rowsCount, stopwatch, sql, sqlParams); + + return ViewRowIdsOrderedSelection.builder() + .setViewId(viewId) + .setSize(rowsCount) + .setOrderBys(sqlBindings.getDefaultOrderBys()) + .setQueryLimit(queryLimit, queryLimitHit) + .build(); } public IViewRow retrieveById(final SqlViewEvaluationCtx viewEvalCtx, final ViewId viewId, final DocumentId rowId) { final WindowId windowId = viewId.getWindowId(); final String viewSelectionId = viewId.getViewId(); - final IViewRowAttributesProvider attributesProvider = null; // TODO final Evaluatee evalCtx = viewEvalCtx.toEvaluatee(); final String sql = sqlBindings.getSqlSelectById().evaluate(evalCtx, OnVariableNotFound.Fail); @@ -109,7 +145,7 @@ public IViewRow retrieveById(final SqlViewEvaluationCtx viewEvalCtx, final ViewI IViewRow firstDocument = null; while (rs.next()) { - final IViewRow document = loadViewRow(rs, windowId, attributesProvider); + final IViewRow document = loadViewRow(rs, windowId); if (document == null) { continue; @@ -144,10 +180,9 @@ public IViewRow retrieveById(final SqlViewEvaluationCtx viewEvalCtx, final ViewI } } - private IViewRow loadViewRow(final ResultSet rs, final WindowId windowId, final IViewRowAttributesProvider attributesProvider) throws SQLException + private IViewRow loadViewRow(final ResultSet rs, final WindowId windowId) throws SQLException { - final ViewRow.Builder viewRowBuilder = ViewRow.builder(windowId) - .setAttributesProvider(attributesProvider); + final ViewRow.Builder viewRowBuilder = ViewRow.builder(windowId); for (final SqlViewRowFieldBinding field : sqlBindings.getFields()) { @@ -184,8 +219,6 @@ public List retrievePage(final SqlViewEvaluationCtx viewEvalCtx, final final WindowId windowId = orderedSelection.getWindowId(); final String viewSelectionId = orderedSelection.getSelectionId(); - final IViewRowAttributesProvider attributesProvider = null; // TODO - final int firstSeqNo = firstRow + 1; // NOTE: firstRow is 0-based while SeqNo are 1-based final int lastSeqNo = firstRow + pageLength; @@ -205,7 +238,7 @@ public List retrievePage(final SqlViewEvaluationCtx viewEvalCtx, final final ImmutableList.Builder pageBuilder = ImmutableList.builder(); while (rs.next()) { - final IViewRow row = loadViewRow(rs, windowId, attributesProvider); + final IViewRow row = loadViewRow(rs, windowId); if (row == null) { continue; diff --git a/src/main/java/de/metas/ui/web/view/ViewRow.java b/src/main/java/de/metas/ui/web/view/ViewRow.java index 40fc56c1d..be7cab8b3 100644 --- a/src/main/java/de/metas/ui/web/view/ViewRow.java +++ b/src/main/java/de/metas/ui/web/view/ViewRow.java @@ -5,8 +5,6 @@ import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -55,8 +53,6 @@ public static final Builder builder(final WindowId windowId) private final Map values; - private final IViewRowAttributesProvider attributesProvider; - private final List includedRows; private ViewRow(final Builder builder) @@ -66,11 +62,9 @@ private ViewRow(final Builder builder) type = builder.getType(); processed = builder.isProcessed(); - values = ImmutableMap.copyOf(builder.values); + values = ImmutableMap.copyOf(builder.getValues()); includedRows = builder.buildIncludedRows(); - - attributesProvider = builder.getAttributesProviderOrNull(); } @Override @@ -81,7 +75,6 @@ public String toString() .add("id", rowId) .add("type", type) .add("values", values) - .add("attributesProvider", attributesProvider) .add("includedRows.count", includedRows.size()) .add("processed", processed) .toString(); @@ -120,27 +113,13 @@ public Map getFieldNameAndJsonValues() @Override public boolean hasAttributes() { - return attributesProvider != null; + return false; } @Override public IViewRowAttributes getAttributes() { - if (rowId == null) - { - throw new EntityNotFoundException("row does not support attributes"); - } - if (attributesProvider == null) - { - throw new EntityNotFoundException("row does not support attributes"); - } - - final IViewRowAttributes attributes = attributesProvider.getAttributes(rowId, null); - if (attributes == null) - { - throw new EntityNotFoundException("row does not support attributes"); - } - return attributes; + throw new EntityNotFoundException("row does not support attributes"); } @Override @@ -164,16 +143,12 @@ public List getIncludedRows() public static final class Builder { private final WindowId windowId; - private DocumentId _rowId; + private DocumentId rowId; private IViewRowType type; private Boolean processed; - - private final Map values = new LinkedHashMap<>(); - + private final Map values = new LinkedHashMap<>(); // preserve the insertion order of fields private List includedRows = null; - private IViewRowAttributesProvider attributesProvider; - private Builder(@NonNull final WindowId windowId) { this.windowId = windowId; @@ -192,7 +167,7 @@ private DocumentPath getDocumentPath() public Builder setRowId(final DocumentId rowId) { - _rowId = rowId; + this.rowId = rowId; return this; } @@ -232,11 +207,11 @@ else if (jsonRowIdObj instanceof JSONLookupValue) /** @return view row ID */ private DocumentId getRowId() { - if (_rowId == null) + if (rowId == null) { throw new IllegalStateException("No rowId was provided for " + this); } - return _rowId; + return rowId; } private IViewRowType getType() @@ -284,15 +259,9 @@ public Builder putFieldValue(final String fieldName, final Object jsonValue) return this; } - private IViewRowAttributesProvider getAttributesProviderOrNull() + private Map getValues() { - return attributesProvider; - } - - public Builder setAttributesProvider(@Nullable final IViewRowAttributesProvider attributesProvider) - { - this.attributesProvider = attributesProvider; - return this; + return values; } public Builder addIncludedRow(final IViewRow includedRow) diff --git a/src/main/java/de/metas/ui/web/view/descriptor/SqlViewBinding.java b/src/main/java/de/metas/ui/web/view/descriptor/SqlViewBinding.java index df424c441..4b1369562 100644 --- a/src/main/java/de/metas/ui/web/view/descriptor/SqlViewBinding.java +++ b/src/main/java/de/metas/ui/web/view/descriptor/SqlViewBinding.java @@ -12,33 +12,22 @@ import org.adempiere.ad.expression.api.impl.CompositeStringExpression; import org.adempiere.ad.expression.api.impl.ConstantStringExpression; import org.adempiere.ad.security.IUserRolePermissions; -import org.adempiere.ad.security.IUserRolePermissionsDAO; -import org.adempiere.ad.security.UserRolePermissionsKey; import org.adempiere.ad.security.impl.AccessSqlStringExpression; -import org.adempiere.ad.security.permissions.WindowMaxQueryRecordsConstraint; -import org.adempiere.ad.trx.api.ITrx; import org.adempiere.util.Check; -import org.adempiere.util.Services; import org.compiere.util.DB; import org.compiere.util.Evaluatee; -import org.slf4j.Logger; import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; -import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import de.metas.logging.LogManager; import de.metas.ui.web.base.model.I_T_WEBUI_ViewSelection; -import de.metas.ui.web.view.IViewRowIdsOrderedSelectionFactory; import de.metas.ui.web.view.SqlViewEvaluationCtx; import de.metas.ui.web.view.ViewId; -import de.metas.ui.web.view.ViewRowIdsOrderedSelection; import de.metas.ui.web.view.descriptor.SqlViewRowFieldBinding.SqlViewRowFieldLoader; import de.metas.ui.web.window.datatypes.DocumentId; -import de.metas.ui.web.window.datatypes.WindowId; import de.metas.ui.web.window.descriptor.filters.DocumentFilterDescriptorsProvider; import de.metas.ui.web.window.descriptor.filters.NullDocumentFilterDescriptorsProvider; import de.metas.ui.web.window.descriptor.sql.SqlEntityBinding; @@ -77,13 +66,11 @@ public static final Builder builder() return new Builder(); } - private static final Logger logger = LogManager.getLogger(SqlViewBinding.class); - // // Paging constants - public static final String COLUMNNAME_Paging_UUID = "_sel_UUID"; - public static final String COLUMNNAME_Paging_SeqNo = "_sel_SeqNo"; - public static final String COLUMNNAME_Paging_Record_ID = "_sel_Record_ID"; + private static final String COLUMNNAME_Paging_UUID = "_sel_UUID"; + private static final String COLUMNNAME_Paging_SeqNo = "_sel_SeqNo"; + private static final String COLUMNNAME_Paging_Record_ID = "_sel_Record_ID"; public static final String PLACEHOLDER_OrderBy = "/* ORDER BY PLACEHOLDER */"; @@ -97,7 +84,7 @@ public static final Builder builder() private final IStringExpression sqlSelectById; private final List rowFieldLoaders; - private final List defaultOrderBys; + private final ImmutableList defaultOrderBys; private final DocumentFilterDescriptorsProvider filterDescriptors; private SqlViewBinding(final Builder builder) @@ -301,11 +288,72 @@ public DocumentFilterDescriptorsProvider getFilterDescriptors() { return filterDescriptors; } + + public List getDefaultOrderBys() + { + return defaultOrderBys; + } + + public Map getSqlOrderBysIndexedByFieldName(final SqlViewEvaluationCtx viewEvalCtx) + { + final Evaluatee evalCtx = viewEvalCtx.toEvaluatee(); + + final ImmutableMap.Builder sqlOrderBysIndexedByFieldName = ImmutableMap.builder(); + for (final SqlViewRowFieldBinding fieldBinding : getFields()) + { + final String fieldOrderBy = fieldBinding.getSqlOrderBy().evaluate(evalCtx, OnVariableNotFound.Fail); + if (Check.isEmpty(fieldOrderBy, true)) + { + continue; + } + + final String fieldName = fieldBinding.getFieldName(); + sqlOrderBysIndexedByFieldName.put(fieldName, fieldOrderBy); + } + + return sqlOrderBysIndexedByFieldName.build(); + } + + public String getSqlCreateSelectionFromSelection() + { + final String sqlTableName = getTableName(); + final String sqlTableAlias = getTableAlias(); + final String keyColumnName = getKeyColumnName(); + final String keyColumnNameFQ = sqlTableAlias + "." + keyColumnName; + + // + // INSERT INTO T_WEBUI_ViewSelection (UUID, Line, Record_ID) + final StringBuilder sqlBuilder = new StringBuilder() + .append("INSERT INTO " + I_T_WEBUI_ViewSelection.Table_Name + " (" + + " " + I_T_WEBUI_ViewSelection.COLUMNNAME_UUID + + ", " + I_T_WEBUI_ViewSelection.COLUMNNAME_Line + + ", " + I_T_WEBUI_ViewSelection.COLUMNNAME_Record_ID + + ")"); - public ViewRowIdsOrderedSelection createOrderedSelection( // - final SqlViewEvaluationCtx viewEvalCtx // - , final WindowId windowId // + // + // SELECT ... FROM T_WEBUI_ViewSelection sel INNER JOIN ourTable WHERE sel.UUID=[fromUUID] + { + sqlBuilder + .append("\n SELECT ") + .append("\n ?") // newUUID + .append("\n, ").append("row_number() OVER (ORDER BY ").append(PLACEHOLDER_OrderBy).append(")") // Line + .append("\n, ").append(keyColumnNameFQ) // Record_ID + .append("\n FROM ").append(I_T_WEBUI_ViewSelection.Table_Name).append(" sel") + .append("\n LEFT OUTER JOIN ").append(sqlTableName).append(" ").append(sqlTableAlias).append(" ON (").append(keyColumnNameFQ).append("=").append("sel.") + .append(I_T_WEBUI_ViewSelection.COLUMNNAME_Record_ID).append(")") + .append("\n WHERE sel.").append(I_T_WEBUI_ViewSelection.COLUMNNAME_UUID).append("=?") // fromUUID + ; + } + + return sqlBuilder.toString(); + } + + public String getSqlCreateSelectionFrom( // + final List sqlParams // + , final SqlViewEvaluationCtx viewEvalCtx // + , final ViewId newViewId // , final List filters // + , final int queryLimit // ) { final Evaluatee evalCtx = viewEvalCtx.toEvaluatee(); @@ -313,11 +361,8 @@ public ViewRowIdsOrderedSelection createOrderedSelection( // final String sqlTableAlias = getTableAlias(); final String keyColumnNameFQ = getKeyColumnName(); - final ViewId viewId = ViewId.random(windowId); - // // INSERT INTO T_WEBUI_ViewSelection (UUID, Line, Record_ID) - final List sqlParams = new ArrayList<>(); final CompositeStringExpression.Builder sqlBuilder = IStringExpression.composer() .append("INSERT INTO " + I_T_WEBUI_ViewSelection.Table_Name + " (" + " " + I_T_WEBUI_ViewSelection.COLUMNNAME_UUID @@ -344,7 +389,7 @@ public ViewRowIdsOrderedSelection createOrderedSelection( // .append("\n WHERE 1=1 ") .wrap(AccessSqlStringExpression.wrapper(sqlTableAlias, IUserRolePermissions.SQL_FULLYQUALIFIED, IUserRolePermissions.SQL_RO)) // security ); - sqlParams.add(viewId.getViewId()); + sqlParams.add(newViewId.getViewId()); } // @@ -364,94 +409,16 @@ public ViewRowIdsOrderedSelection createOrderedSelection( // // // Enforce a LIMIT, to not affect server performances on huge tables - final int queryLimit; + if (queryLimit > 0) { - final UserRolePermissionsKey permissionsKey = UserRolePermissionsKey.fromEvaluatee(evalCtx, AccessSqlStringExpression.PARAM_UserRolePermissionsKey.getName()); - final IUserRolePermissions permissions = Services.get(IUserRolePermissionsDAO.class).retrieveUserRolePermissions(permissionsKey); - - queryLimit = permissions.getConstraint(WindowMaxQueryRecordsConstraint.class) - .or(WindowMaxQueryRecordsConstraint.DEFAULT) - .getMaxQueryRecordsPerRole(); - if (queryLimit > 0) - { - sqlBuilder.append("\n LIMIT ?"); - sqlParams.add(queryLimit); - } + sqlBuilder.append("\n LIMIT ?"); + sqlParams.add(queryLimit); } // // Evaluate the final SQL query final String sql = sqlBuilder.build().evaluate(evalCtx, OnVariableNotFound.Fail); - - // - // Execute it, so we insert in our T_WEBUI_ViewSelection - final Stopwatch stopwatch = Stopwatch.createStarted(); - final long rowsCount = DB.executeUpdateEx(sql, sqlParams.toArray(), ITrx.TRXNAME_ThreadInherited); - stopwatch.stop(); - final boolean queryLimitHit = queryLimit > 0 && rowsCount >= queryLimit; - logger.trace("Created selection {}, rowsCount={}, duration={} \n SQL: {} -- {}", viewId, rowsCount, stopwatch, sql, sqlParams); - - return ViewRowIdsOrderedSelection.builder() - .setViewId(viewId) - .setSize(rowsCount) - .setOrderBys(defaultOrderBys) - .setQueryLimit(queryLimit, queryLimitHit) - .build(); - } - - public IViewRowIdsOrderedSelectionFactory createOrderedSelectionFactory(final SqlViewEvaluationCtx viewEvalCtx) - { - final Evaluatee evalCtx = viewEvalCtx.toEvaluatee(); - final String sqlCreateFromViewId = getSqlCreateSelectionFromSelection(); - - final ImmutableMap.Builder sqlOrderBysByFieldName = ImmutableMap.builder(); - for (final SqlViewRowFieldBinding fieldBinding : getFields()) - { - final String fieldOrderBy = fieldBinding.getSqlOrderBy().evaluate(evalCtx, OnVariableNotFound.Fail); - if (Check.isEmpty(fieldOrderBy, true)) - { - continue; - } - - final String fieldName = fieldBinding.getFieldName(); - sqlOrderBysByFieldName.put(fieldName, fieldOrderBy); - } - - return new SqlViewRowIdsOrderedSelectionFactory(sqlCreateFromViewId, sqlOrderBysByFieldName.build()); - } - - private String getSqlCreateSelectionFromSelection() - { - final String sqlTableName = getTableName(); - final String sqlTableAlias = getTableAlias(); - final String keyColumnName = getKeyColumnName(); - final String keyColumnNameFQ = sqlTableAlias + "." + keyColumnName; - - // - // INSERT INTO T_WEBUI_ViewSelection (UUID, Line, Record_ID) - final StringBuilder sqlBuilder = new StringBuilder() - .append("INSERT INTO " + I_T_WEBUI_ViewSelection.Table_Name + " (" - + " " + I_T_WEBUI_ViewSelection.COLUMNNAME_UUID - + ", " + I_T_WEBUI_ViewSelection.COLUMNNAME_Line - + ", " + I_T_WEBUI_ViewSelection.COLUMNNAME_Record_ID - + ")"); - - // - // SELECT ... FROM T_WEBUI_ViewSelection sel INNER JOIN ourTable WHERE sel.UUID=[fromUUID] - { - sqlBuilder - .append("\n SELECT ") - .append("\n ?") // newUUID - .append("\n, ").append("row_number() OVER (ORDER BY ").append(PLACEHOLDER_OrderBy).append(")") // Line - .append("\n, ").append(keyColumnNameFQ) // Record_ID - .append("\n FROM ").append(I_T_WEBUI_ViewSelection.Table_Name).append(" sel") - .append("\n LEFT OUTER JOIN ").append(sqlTableName).append(" ").append(sqlTableAlias).append(" ON (").append(keyColumnNameFQ).append("=").append("sel.") - .append(I_T_WEBUI_ViewSelection.COLUMNNAME_Record_ID).append(")") - .append("\n WHERE sel.").append(I_T_WEBUI_ViewSelection.COLUMNNAME_UUID).append("=?") // fromUUID - ; - } - - return sqlBuilder.toString(); + return sql; } // diff --git a/src/main/java/de/metas/ui/web/view/descriptor/SqlViewRowIdsOrderedSelectionFactory.java b/src/main/java/de/metas/ui/web/view/descriptor/SqlViewRowIdsOrderedSelectionFactory.java index 2a48f4c33..d76622459 100644 --- a/src/main/java/de/metas/ui/web/view/descriptor/SqlViewRowIdsOrderedSelectionFactory.java +++ b/src/main/java/de/metas/ui/web/view/descriptor/SqlViewRowIdsOrderedSelectionFactory.java @@ -40,12 +40,12 @@ * #L% */ -class SqlViewRowIdsOrderedSelectionFactory implements IViewRowIdsOrderedSelectionFactory +public class SqlViewRowIdsOrderedSelectionFactory implements IViewRowIdsOrderedSelectionFactory { private final String sqlCreateFromViewId; private final Map sqlOrderBysByFieldName; - SqlViewRowIdsOrderedSelectionFactory(final String sqlCreateFromViewId, final Map sqlOrderBysByFieldName) + public SqlViewRowIdsOrderedSelectionFactory(final String sqlCreateFromViewId, final Map sqlOrderBysByFieldName) { super(); this.sqlCreateFromViewId = sqlCreateFromViewId;