This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 5ca8eb1eb6 issue #7394 : Dimension Lookup - add lots of checks (#7408)
5ca8eb1eb6 is described below
commit 5ca8eb1eb606d1b54932b02b76c0500247d923c0
Author: Matt Casters <[email protected]>
AuthorDate: Fri Jul 3 07:35:49 2026 +0200
issue #7394 : Dimension Lookup - add lots of checks (#7408)
---
.../dimensionlookup/DimensionLookup.java | 376 ++++++++++++++++-----
.../dimensionlookup/DimensionLookupMeta.java | 7 +
.../messages/messages_en_US.properties | 13 +-
3 files changed, 303 insertions(+), 93 deletions(-)
diff --git
a/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookup.java
b/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookup.java
index da051f4f24..0284466f33 100644
---
a/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookup.java
+++
b/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookup.java
@@ -95,121 +95,133 @@ public class DimensionLookup extends
BaseTransform<DimensionLookupMeta, Dimensio
if (first) {
first = false;
+ try {
+ data.schemaTable =
+ data.databaseMeta.getQuotedSchemaTableCombination(
+ this, data.realSchemaName, data.realTableName);
- data.schemaTable =
- data.databaseMeta.getQuotedSchemaTableCombination(
- this, data.realSchemaName, data.realTableName);
+ data.inputRowMeta = getInputRowMeta().clone();
+ data.outputRowMeta = getInputRowMeta().clone();
+ meta.getFields(data.outputRowMeta, getTransformName(), null, null,
this, metadataProvider);
- data.inputRowMeta = getInputRowMeta().clone();
- data.outputRowMeta = getInputRowMeta().clone();
- meta.getFields(data.outputRowMeta, getTransformName(), null, null, this,
metadataProvider);
+ DLFields f = meta.getFields();
- // Get the fields that need conversion to normal storage...
- // Modify the storage type of the input data...
- //
- data.lazyList = new ArrayList<>();
- for (int i = 0; i < data.inputRowMeta.size(); i++) {
- IValueMeta valueMeta = data.inputRowMeta.getValueMeta(i);
- if (valueMeta.isStorageBinaryString()) {
- data.lazyList.add(i);
- valueMeta.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
- }
- }
+ validateFieldsAndMetadata(f);
- // The start date value column (if applicable)
- //
- data.startDateFieldIndex = -1;
- if (data.startDateAlternative == COLUMN_VALUE) {
- data.startDateFieldIndex =
data.inputRowMeta.indexOfValue(meta.getStartDateFieldName());
- if (data.startDateFieldIndex < 0) {
- throw new HopTransformException(
- BaseMessages.getString(
- PKG,
- "DimensionLookup.Exception.StartDateValueColumnNotFound",
- meta.getStartDateFieldName()));
+ // Get the fields that need conversion to normal storage...
+ // Modify the storage type of the input data...
+ //
+ data.lazyList = new ArrayList<>();
+ for (int i = 0; i < data.inputRowMeta.size(); i++) {
+ IValueMeta valueMeta = data.inputRowMeta.getValueMeta(i);
+ if (valueMeta.isStorageBinaryString()) {
+ data.lazyList.add(i);
+ valueMeta.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
+ }
}
- }
- DLFields f = meta.getFields();
-
- // Lookup values
- data.keynrs = new int[f.getKeys().size()];
- for (int i = 0; i < data.keynrs.length; i++) {
- DLKey key = f.getKeys().get(i);
- data.keynrs[i] = data.inputRowMeta.indexOfValue(key.getName());
- if (data.keynrs[i] < 0) { // couldn't find field!
- throw new HopTransformException(
- BaseMessages.getString(
- PKG, CONST_DIMENSION_LOOKUP_EXCEPTION_KEY_FIELD_NOT_FOUND,
key.getName()));
+ // The start date value column (if applicable)
+ //
+ data.startDateFieldIndex = -1;
+ if (data.startDateAlternative == COLUMN_VALUE) {
+ data.startDateFieldIndex =
data.inputRowMeta.indexOfValue(meta.getStartDateFieldName());
+ if (data.startDateFieldIndex < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.StartDateValueColumnNotFound",
+ meta.getStartDateFieldName()));
+ }
}
- }
- // Return values
- data.fieldnrs = new int[f.getFields().size()];
- for (int i = 0; i < data.fieldnrs.length; i++) {
- DLField field = f.getFields().get(i);
- if (isLookupOrUpdateTypeWithArgument(meta.isUpdate(), field)) {
- data.fieldnrs[i] = data.outputRowMeta.indexOfValue(field.getName());
- if (data.fieldnrs[i] < 0) {
+ // Lookup values
+ data.keynrs = new int[f.getKeys().size()];
+ for (int i = 0; i < data.keynrs.length; i++) {
+ DLKey key = f.getKeys().get(i);
+
+ data.keynrs[i] = data.inputRowMeta.indexOfValue(key.getName());
+ if (data.keynrs[i] < 0) { // couldn't find field!
throw new HopTransformException(
BaseMessages.getString(
- PKG, CONST_DIMENSION_LOOKUP_EXCEPTION_KEY_FIELD_NOT_FOUND,
field.getName()));
+ PKG, CONST_DIMENSION_LOOKUP_EXCEPTION_KEY_FIELD_NOT_FOUND,
key.getName()));
}
- } else {
- data.fieldnrs[i] = -1;
}
- }
- if (!meta.isUpdate() && meta.isPreloadingCache()) {
- preloadCache();
- } else {
- // Caching...
- //
- if (data.cacheKeyRowMeta == null) {
- // KEY : the natural key(s)
+ // Return values
+ data.fieldnrs = new int[f.getFields().size()];
+ for (int i = 0; i < data.fieldnrs.length; i++) {
+ DLField field = f.getFields().get(i);
+ if (isLookupOrUpdateTypeWithArgument(meta.isUpdate(), field)) {
+ data.fieldnrs[i] =
data.outputRowMeta.indexOfValue(field.getName());
+ if (data.fieldnrs[i] < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
CONST_DIMENSION_LOOKUP_EXCEPTION_KEY_FIELD_NOT_FOUND, field.getName()));
+ }
+ } else {
+ data.fieldnrs[i] = -1;
+ }
+ }
+
+ if (!meta.isUpdate() && meta.isPreloadingCache()) {
+ preloadCache();
+ } else {
+ // Caching...
//
- data.cacheKeyRowMeta = new RowMeta();
- for (int i = 0; i < data.keynrs.length; i++) {
- IValueMeta key = data.inputRowMeta.getValueMeta(data.keynrs[i]);
- data.cacheKeyRowMeta.addValueMeta(key.clone());
+ if (data.cacheKeyRowMeta == null) {
+ // KEY : the natural key(s)
+ //
+ data.cacheKeyRowMeta = new RowMeta();
+ for (int i = 0; i < data.keynrs.length; i++) {
+ IValueMeta key = data.inputRowMeta.getValueMeta(data.keynrs[i]);
+ data.cacheKeyRowMeta.addValueMeta(key.clone());
+ }
+
+ data.cache =
+ new ByteArrayHashMap(
+ meta.getCacheSize() > 0 ? meta.getCacheSize() : 5000,
data.cacheKeyRowMeta);
}
+ }
- data.cache =
- new ByteArrayHashMap(
- meta.getCacheSize() > 0 ? meta.getCacheSize() : 5000,
data.cacheKeyRowMeta);
+ if (StringUtils.isNotEmpty(f.getDate().getName())) {
+ data.datefieldnr =
data.inputRowMeta.indexOfValue(f.getDate().getName());
+ } else {
+ data.datefieldnr = -1;
}
- }
- if (StringUtils.isNotEmpty(f.getDate().getName())) {
- data.datefieldnr =
data.inputRowMeta.indexOfValue(f.getDate().getName());
- } else {
- data.datefieldnr = -1;
- }
+ // Initialize the start date value in case we don't have one in the
input rows
+ //
+ data.valueDateNow = determineDimensionUpdatedDate(r);
- // Initialize the start date value in case we don't have one in the
input rows
- //
- data.valueDateNow = determineDimensionUpdatedDate(r);
+ if (meta.getFields().getReturns().getCreationMethod() ==
TechnicalKeyCreationMethod.FIELD) {
+ String tkSourceField = resolve(meta.getTkSourceField());
+ data.tkFieldIndex = getInputRowMeta().indexOfValue(tkSourceField);
+ }
- if (meta.getFields().getReturns().getCreationMethod() ==
TechnicalKeyCreationMethod.FIELD) {
- String tkSourceField = resolve(meta.getTkSourceField());
- data.tkFieldIndex = getInputRowMeta().indexOfValue(tkSourceField);
- }
+ data.tkFieldType =
+ meta.buildTkValueMeta(
+ getInputRowMeta(),
meta.getFields().getReturns().getKeyField(), this);
- data.tkFieldType =
- meta.buildTkValueMeta(
- getInputRowMeta(), meta.getFields().getReturns().getKeyField(),
this);
+ data.notFoundTk =
+ determineNotFoundTk(
+ data.tkFieldType,
+ meta.getFields().getReturns().getCreationMethod(),
+ data.databaseMeta);
- data.notFoundTk =
- determineNotFoundTk(
- data.tkFieldType,
- meta.getFields().getReturns().getCreationMethod(),
- data.databaseMeta);
+ if (getCopy() == 0) {
+ checkDimZero();
+ }
- if (getCopy() == 0) {
- checkDimZero();
+ setDimLookup(data.outputRowMeta);
+ } catch (HopException e) {
+ logError(
+ BaseMessages.getString(
+ PKG, "DimensionLookup.Log.TransformCanNotContinueForErrors",
e.getMessage()));
+ setErrors(1);
+ stopAll();
+ setOutputDone();
+ return false;
}
-
- setDimLookup(data.outputRowMeta);
}
// convert row to normal storage...
@@ -236,7 +248,9 @@ public class DimensionLookup extends
BaseTransform<DimensionLookupMeta, Dimensio
logError(
BaseMessages.getString(
PKG, "DimensionLookup.Log.TransformCanNotContinueForErrors",
e.getMessage()));
- logError(Const.getStackTracker(e));
+ if (!(e instanceof HopTransformException)) {
+ logError(Const.getStackTracker(e));
+ }
setErrors(1);
stopAll();
setOutputDone(); // signal end to receiver(s)
@@ -373,9 +387,33 @@ public class DimensionLookup extends
BaseTransform<DimensionLookupMeta, Dimensio
DLKey key = f.getKeys().get(i);
// The field in the table:
data.preloadKeyIndexes[i] = rowMeta.indexOfValue(key.getLookup());
+ if (data.preloadKeyIndexes[i] < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.LookupKeyFieldNotFound",
+ key.getLookup(),
+ data.schemaTable));
+ }
}
data.preloadFromDateIndex = rowMeta.indexOfValue(f.getDate().getFrom());
+ if (data.preloadFromDateIndex < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.StartDateFromFieldNotFound",
+ f.getDate().getFrom(),
+ data.schemaTable));
+ }
data.preloadToDateIndex = rowMeta.indexOfValue(f.getDate().getTo());
+ if (data.preloadToDateIndex < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.StartDateToFieldNotFound",
+ f.getDate().getTo(),
+ data.schemaTable));
+ }
data.preloadCache =
new DimensionCache(
@@ -1899,6 +1937,160 @@ public class DimensionLookup extends
BaseTransform<DimensionLookupMeta, Dimensio
}
}
+ private void validateFieldsAndMetadata(DLFields f) throws HopException {
+ // 1. Retrieve target database table fields
+ IRowMeta tableFields;
+ try {
+ tableFields = data.db.getTableFieldsMeta(data.realSchemaName,
data.realTableName);
+ } catch (Exception e) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, "DimensionLookup.Exception.UnableToReadTableMetadata",
data.schemaTable),
+ e);
+ }
+ if (tableFields == null) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, "DimensionLookup.Exception.UnableToReadTableMetadata",
data.schemaTable));
+ }
+
+ // 2. Validate core database columns exist
+ String tkField = f.getReturns().getKeyField();
+ if (StringUtils.isNotEmpty(tkField)) {
+ if (tableFields.indexOfValue(tkField) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.TechnicalKeyFieldNotFound",
+ tkField,
+ data.schemaTable));
+ }
+ } else {
+ throw new HopTransformException(
+ BaseMessages.getString(PKG,
"DimensionLookupMeta.Error.NoTechnicalKeySpecified"));
+ }
+
+ String versionField = f.getReturns().getVersionField();
+ if (StringUtils.isNotEmpty(versionField)) {
+ if (tableFields.indexOfValue(versionField) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.VersionFieldNotFound",
+ versionField,
+ data.schemaTable));
+ }
+ } else {
+ throw new HopTransformException(
+ BaseMessages.getString(PKG,
"DimensionLookupMeta.CheckResult.VersionKeyRequired"));
+ }
+
+ String fromField = f.getDate().getFrom();
+ if (StringUtils.isNotEmpty(fromField)) {
+ if (tableFields.indexOfValue(fromField) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.StartDateFromFieldNotFound",
+ fromField,
+ data.schemaTable));
+ }
+ } else {
+ throw new HopTransformException(
+ BaseMessages.getString(PKG,
"DimensionLookupMeta.CheckResult.StartKeyRequired"));
+ }
+
+ String toField = f.getDate().getTo();
+ if (StringUtils.isNotEmpty(toField)) {
+ if (tableFields.indexOfValue(toField) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.StartDateToFieldNotFound",
+ toField,
+ data.schemaTable));
+ }
+ } else {
+ throw new HopTransformException(
+ BaseMessages.getString(PKG,
"DimensionLookupMeta.CheckResult.EndKeyRequired"));
+ }
+
+ // 3. Validate key lookup columns in database table
+ for (DLKey key : f.getKeys()) {
+ String keyLookup = key.getLookup();
+ if (StringUtils.isNotEmpty(keyLookup)) {
+ if (tableFields.indexOfValue(keyLookup) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.LookupKeyFieldNotFound",
+ keyLookup,
+ data.schemaTable));
+ }
+ }
+ }
+
+ // 4. Validate output/update lookup columns in database table
+ for (DLField field : f.getFields()) {
+ if (isLookupOrUpdateTypeWithArgument(meta.isUpdate(), field)) {
+ String fieldLookup = field.getLookup();
+ if (StringUtils.isNotEmpty(fieldLookup)) {
+ if (tableFields.indexOfValue(fieldLookup) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "DimensionLookup.Exception.LookupOrUpdateFieldNotFound",
+ fieldLookup,
+ data.schemaTable));
+ }
+ }
+ }
+ }
+
+ // 5. Validate input stream fields
+ // Date Field
+ String dateName = f.getDate().getName();
+ if (StringUtils.isNotEmpty(dateName)) {
+ if (data.inputRowMeta.indexOfValue(dateName) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, "DimensionLookup.Exception.DateFieldNameNotFound",
dateName));
+ }
+ }
+
+ // Technical Key Source Field
+ if (f.getReturns().getCreationMethod() ==
TechnicalKeyCreationMethod.FIELD) {
+ String tkSourceField = resolve(meta.getTkSourceField());
+ if (StringUtils.isEmpty(tkSourceField) ||
data.inputRowMeta.indexOfValue(tkSourceField) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, "DimensionLookup.Exception.TkSourceFieldNotFound",
tkSourceField));
+ }
+ }
+
+ // Keys in stream
+ for (DLKey key : f.getKeys()) {
+ if (data.inputRowMeta.indexOfValue(key.getName()) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, CONST_DIMENSION_LOOKUP_EXCEPTION_KEY_FIELD_NOT_FOUND,
key.getName()));
+ }
+ }
+
+ // Update source fields in stream (only if update is true)
+ if (meta.isUpdate()) {
+ for (DLField field : f.getFields()) {
+ if (isLookupOrUpdateTypeWithArgument(meta.isUpdate(), field)) {
+ if (data.outputRowMeta.indexOfValue(field.getName()) < 0) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
"DimensionLookup.Exception.UpdateSourceFieldNotFound", field.getName()));
+ }
+ }
+ }
+ }
+ }
+
@Override
public boolean init() {
diff --git
a/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookupMeta.java
b/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookupMeta.java
index 920da12837..b394858ae3 100644
---
a/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookupMeta.java
+++
b/plugins/transforms/dimensionlookup/src/main/java/org/apache/hop/pipeline/transforms/dimensionlookup/DimensionLookupMeta.java
@@ -311,6 +311,13 @@ public class DimensionLookupMeta extends
BaseTransformMeta<DimensionLookup, Dime
try {
// Get the rows from the table...
IRowMeta extraFields = getTableFields(variables);
+ if (extraFields == null) {
+ String message =
+ BaseMessages.getString(
+ PKG,
"DimensionLookupMeta.Exception.UnableToRetrieveDataTypeOfReturnField");
+ logError(message);
+ throw new HopTransformException(message);
+ }
for (DLField field : fields.fields) {
IValueMeta lookupValueMeta =
extraFields.searchValueMeta(field.getLookup());
diff --git
a/plugins/transforms/dimensionlookup/src/main/resources/org/apache/hop/pipeline/transforms/dimensionlookup/messages/messages_en_US.properties
b/plugins/transforms/dimensionlookup/src/main/resources/org/apache/hop/pipeline/transforms/dimensionlookup/messages/messages_en_US.properties
index c9c20dfdfd..5a08374572 100644
---
a/plugins/transforms/dimensionlookup/src/main/resources/org/apache/hop/pipeline/transforms/dimensionlookup/messages/messages_en_US.properties
+++
b/plugins/transforms/dimensionlookup/src/main/resources/org/apache/hop/pipeline/transforms/dimensionlookup/messages/messages_en_US.properties
@@ -225,4 +225,15 @@ DimensionLookupDialog.Uuid.Label=Use a new UUID
DimensionLookupDialog.UuidButton.Tooltip=Generate a new UUID as
technical/surrogate key
DimensionLookupDialog.TkField.Label = Input field
DimensionLookupDialog.TkField.Tooltip = Specify the name of the field in the
input to use as a technical/surrogate key.
-DimensionLookupDialog.ShowUnknownTk.Label = Display selected unknown value
\ No newline at end of file
+DimensionLookupDialog.ShowUnknownTk.Label = Display selected unknown value
+
+DimensionLookup.Exception.UnableToReadTableMetadata=Could not read fields for
target table [{0}]. Make sure the table exists.
+DimensionLookup.Exception.TechnicalKeyFieldNotFound=Technical key field [{0}]
not found in table [{1}].
+DimensionLookup.Exception.VersionFieldNotFound=Version field [{0}] not found
in table [{1}].
+DimensionLookup.Exception.StartDateFromFieldNotFound=Date-From field [{0}] not
found in table [{1}].
+DimensionLookup.Exception.StartDateToFieldNotFound=Date-To field [{0}] not
found in table [{1}].
+DimensionLookup.Exception.LookupKeyFieldNotFound=Lookup key column [{0}] not
found in table [{1}].
+DimensionLookup.Exception.LookupOrUpdateFieldNotFound=Lookup/update column
[{0}] not found in table [{1}].
+DimensionLookup.Exception.DateFieldNameNotFound=Date field [{0}] could not be
found in the input stream.
+DimensionLookup.Exception.TkSourceFieldNotFound=Technical key source field
[{0}] could not be found in the input stream.
+DimensionLookup.Exception.UpdateSourceFieldNotFound=Update source field [{0}]
could not be found in the input stream.
\ No newline at end of file