diff --git a/jOOQ/src/main/java/org/jooq/LoaderCSVStep.java b/jOOQ/src/main/java/org/jooq/LoaderCSVStep.java index 039a5503b4..ba5666e3d0 100644 --- a/jOOQ/src/main/java/org/jooq/LoaderCSVStep.java +++ b/jOOQ/src/main/java/org/jooq/LoaderCSVStep.java @@ -40,6 +40,7 @@ package org.jooq; import java.util.Collection; import org.jooq.LoaderFieldMapper.LoaderFieldContext; +import org.jooq.exception.LoaderConfigurationException; /** * The Loader API is used for configuring data loads. @@ -102,4 +103,16 @@ public interface LoaderCSVStep { */ @Support LoaderCSVOptionsStep fields(LoaderFieldMapper mapper); + + /** + * Indicate that all input fields which have a corresponding field in the + * target table (with the same name) should be loaded. + *

+ * When {@link LoaderLoadStep#execute() executing the loader} input fields + * for which there is no match in the target table will be logged and if no + * field names can be derived for the input data a + * {@link LoaderConfigurationException} will be reported. + */ + @Support + LoaderCSVOptionsStep fieldsFromSource(); } diff --git a/jOOQ/src/main/java/org/jooq/LoaderJSONStep.java b/jOOQ/src/main/java/org/jooq/LoaderJSONStep.java index df1947014a..63792cd037 100644 --- a/jOOQ/src/main/java/org/jooq/LoaderJSONStep.java +++ b/jOOQ/src/main/java/org/jooq/LoaderJSONStep.java @@ -40,6 +40,7 @@ package org.jooq; import java.util.Collection; import org.jooq.LoaderFieldMapper.LoaderFieldContext; +import org.jooq.exception.LoaderConfigurationException; /** * The Loader API is used for configuring data loads. @@ -53,7 +54,7 @@ import org.jooq.LoaderFieldMapper.LoaderFieldContext; public interface LoaderJSONStep { /** - * Specify the the fields to be loaded into the table in the correct order. + * Specify the fields to be loaded into the table in the correct order. *

* The JSON column at index i is inserted into the table field * at index i. If fields[i] == null or @@ -64,7 +65,7 @@ public interface LoaderJSONStep { LoaderJSONOptionsStep fields(Field... fields); /** - * Specify the the fields to be loaded into the table in the correct order. + * Specify the fields to be loaded into the table in the correct order. *

* The JSON column at index i is inserted into the table field * at index i. If @@ -86,4 +87,16 @@ public interface LoaderJSONStep { */ @Support LoaderJSONOptionsStep fields(LoaderFieldMapper mapper); + + /** + * Indicate that all input fields which have a corresponding field in the + * target table (with the same name) should be loaded. + *

+ * When {@link LoaderLoadStep#execute() executing the loader} input fields + * for which there is no match in the target table will be logged and if no + * field names can be derived for the input data a + * {@link LoaderConfigurationException} will be reported. + */ + @Support + LoaderJSONOptionsStep fieldsFromSource(); } diff --git a/jOOQ/src/main/java/org/jooq/LoaderRowsStep.java b/jOOQ/src/main/java/org/jooq/LoaderRowsStep.java index dc2418cf01..29ab25f36d 100644 --- a/jOOQ/src/main/java/org/jooq/LoaderRowsStep.java +++ b/jOOQ/src/main/java/org/jooq/LoaderRowsStep.java @@ -40,6 +40,7 @@ package org.jooq; import java.util.Collection; import org.jooq.LoaderFieldMapper.LoaderFieldContext; +import org.jooq.exception.LoaderConfigurationException; /** * The Loader API is used for configuring data loads. @@ -103,4 +104,15 @@ public interface LoaderRowsStep { @Support LoaderListenerStep fields(LoaderFieldMapper mapper); + /** + * Indicate that all input fields which have a corresponding field in the + * target table (with the same name) should be loaded. + *

+ * When {@link LoaderLoadStep#execute() executing the loader} input fields + * for which there is no match in the target table will be logged and if no + * field names can be derived for the input data a + * {@link LoaderConfigurationException} will be reported. + */ + @Support + LoaderListenerStep fieldsFromSource(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java index aee661275f..688416e969 100644 --- a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java @@ -82,6 +82,7 @@ import org.jooq.Source; import org.jooq.Table; import org.jooq.exception.DataAccessException; import org.jooq.exception.LoaderConfigurationException; +import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; import org.jooq.tools.csv.CSVParser; import org.jooq.tools.csv.CSVReader; @@ -104,6 +105,8 @@ final class LoaderImpl implements LoaderJSONOptionsStep, Loader { + private static final JooqLogger log = JooqLogger.getLogger(LoaderImpl.class); + // Configuration constants // ----------------------- private static final int ON_DUPLICATE_KEY_ERROR = 0; @@ -156,6 +159,7 @@ final class LoaderImpl implements private Field[] source; private Field[] fields; private LoaderFieldMapper fieldMapper; + private boolean fieldsFromSource; private boolean[] primaryKey; // Result data @@ -547,29 +551,46 @@ final class LoaderImpl implements return this; } + @Override + public LoaderImpl fieldsFromSource() { + fieldsFromSource = true; + return this; + } + private final void fields0(Object[] row) { Field[] f = new Field[row.length]; // [#5145] When loading arrays, or when CSV headers are ignored, // the source is still null at this stage. if (source == null) - source = Tools.fields(row.length); + if (fieldsFromSource) + throw new LoaderConfigurationException("Using fieldsFromSource() requires field names to be available in source."); + else + source = Tools.fields(row.length); - for (int i = 0; i < row.length; i++) { - final int index = i; + if (fieldMapper != null) + for (int i = 0; i < row.length; i++) { + final int index = i; - f[i] = fieldMapper.map(new LoaderFieldContext() { - @Override - public int index() { - return index; - } + f[i] = fieldMapper.map(new LoaderFieldContext() { + @Override + public int index() { + return index; + } - @Override - public Field field() { - return source[index]; - } - }); - } + @Override + public Field field() { + return source[index]; + } + }); + } + + else if (fieldsFromSource) + for (int i = 0; i < row.length; i++) { + f[i] = table.field(source[i]); + if (f[i] == null) + log.info("No column in target table " + table + " found for input field " + source[i]); + } fields(f); } @@ -721,8 +742,8 @@ final class LoaderImpl implements if (row.getClass() != Object[].class) row = Arrays.copyOf(row, row.length, Object[].class); - // [#5145] Lazy initialisation of fields off the first row - // in case LoaderFieldMapper was used. + // [#5145][#8755] Lazy initialisation of fields from the first row + // in case fields(LoaderFieldMapper) or fieldsFromSource() was used if (fields == null) fields0(row);