embulk 0.8.35-java → 0.8.36-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/build.gradle +1 -1
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkExample.java +5 -1
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkRun.java +12 -0
- data/embulk-core/src/main/java/org/embulk/EmbulkRunner.java +2 -2
- data/embulk-core/src/main/java/org/embulk/plugin/PluginClassLoader.java +802 -17
- data/embulk-core/src/main/java/org/embulk/plugin/PluginClassLoaderFactory.java +8 -1
- data/embulk-core/src/main/java/org/embulk/plugin/PluginClassLoaderModule.java +33 -2
- data/embulk-core/src/main/java/org/embulk/plugin/jar/JarPluginLoader.java +32 -5
- data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +1 -6
- data/embulk-core/src/main/java/org/embulk/spi/json/RubyValueApi.java +39 -1
- data/embulk-core/src/main/java/org/embulk/spi/time/Timestamp.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/DynamicColumnSetterFactory.java +43 -9
- data/embulk-core/src/main/java/org/embulk/spi/util/DynamicPageBuilder.java +46 -8
- data/embulk-core/src/main/java/org/embulk/spi/util/PagePrinter.java +19 -1
- data/embulk-core/src/main/java/org/embulk/spi/util/dynamic/AbstractDynamicColumnSetter.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/dynamic/SkipColumnSetter.java +12 -1
- data/embulk-core/src/main/resources/embulk/parent_first_packages.properties +1 -0
- data/embulk-docs/build.gradle +8 -0
- data/embulk-docs/src/built-in.rst +47 -35
- data/embulk-docs/src/index.rst +9 -1
- data/embulk-docs/src/release.rst +1 -0
- data/embulk-docs/src/release/release-0.8.36.rst +32 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +22 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvTokenizer.java +34 -1
- data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +8 -2
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvTokenizer.java +76 -0
- data/lib/embulk/guess/schema_guess.rb +1 -1
- data/lib/embulk/input_plugin.rb +8 -1
- data/lib/embulk/page_builder.rb +38 -5
- data/lib/embulk/schema.rb +5 -6
- data/lib/embulk/version.rb +1 -1
- data/test/guess/test_schema_guess.rb +18 -0
- metadata +7 -6
@@ -5,5 +5,12 @@ import java.net.URL;
|
|
5
5
|
|
6
6
|
public interface PluginClassLoaderFactory
|
7
7
|
{
|
8
|
-
PluginClassLoader create(Collection<URL>
|
8
|
+
PluginClassLoader create(Collection<URL> flatJarUrls, ClassLoader parentClassLoader);
|
9
|
+
PluginClassLoader createForNestedJar(
|
10
|
+
final ClassLoader parentClassLoader,
|
11
|
+
final URL oneNestedJarUrl);
|
12
|
+
PluginClassLoader createForNestedJar(
|
13
|
+
final ClassLoader parentClassLoader,
|
14
|
+
final URL oneNestedJarUrl,
|
15
|
+
final Collection<String> embeddedJarPathsInNestedJar);
|
9
16
|
}
|
@@ -61,10 +61,41 @@ public class PluginClassLoaderModule
|
|
61
61
|
|
62
62
|
private class Factory implements PluginClassLoaderFactory
|
63
63
|
{
|
64
|
+
@Override
|
64
65
|
public PluginClassLoader create(Collection<URL> urls, ClassLoader parentClassLoader)
|
65
66
|
{
|
66
|
-
return
|
67
|
-
|
67
|
+
return PluginClassLoader.createForFlatJars(
|
68
|
+
parentClassLoader,
|
69
|
+
urls,
|
70
|
+
parentFirstPackages,
|
71
|
+
parentFirstResources);
|
72
|
+
}
|
73
|
+
|
74
|
+
@Override
|
75
|
+
public PluginClassLoader createForNestedJar(
|
76
|
+
final ClassLoader parentClassLoader,
|
77
|
+
final URL oneNestedJarUrl)
|
78
|
+
{
|
79
|
+
return PluginClassLoader.createForNestedJar(
|
80
|
+
parentClassLoader,
|
81
|
+
oneNestedJarUrl,
|
82
|
+
null,
|
83
|
+
parentFirstPackages,
|
84
|
+
parentFirstResources);
|
85
|
+
}
|
86
|
+
|
87
|
+
@Override
|
88
|
+
public PluginClassLoader createForNestedJar(
|
89
|
+
final ClassLoader parentClassLoader,
|
90
|
+
final URL oneNestedJarUrl,
|
91
|
+
final Collection<String> embeddedJarPathsInNestedJar)
|
92
|
+
{
|
93
|
+
return PluginClassLoader.createForNestedJar(
|
94
|
+
parentClassLoader,
|
95
|
+
oneNestedJarUrl,
|
96
|
+
embeddedJarPathsInNestedJar,
|
97
|
+
parentFirstPackages,
|
98
|
+
parentFirstResources);
|
68
99
|
}
|
69
100
|
}
|
70
101
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
package org.embulk.plugin.jar;
|
2
2
|
|
3
|
-
import com.google.common.collect.ImmutableList;
|
4
3
|
import java.io.IOError;
|
5
4
|
import java.io.IOException;
|
6
5
|
import java.net.JarURLConnection;
|
@@ -8,6 +7,9 @@ import java.net.MalformedURLException;
|
|
8
7
|
import java.net.URI;
|
9
8
|
import java.net.URL;
|
10
9
|
import java.nio.file.Path;
|
10
|
+
import java.util.ArrayList;
|
11
|
+
import java.util.Collections;
|
12
|
+
import java.util.List;
|
11
13
|
import java.util.jar.Attributes;
|
12
14
|
import java.util.jar.Manifest;
|
13
15
|
import org.embulk.plugin.PluginClassLoader;
|
@@ -24,6 +26,7 @@ public class JarPluginLoader
|
|
24
26
|
{
|
25
27
|
public static final String MANIFEST_PLUGIN_MAIN_CLASS = "Embulk-Plugin-Main-Class";
|
26
28
|
public static final String MANIFEST_PLUGIN_SPI_VERSION = "Embulk-Plugin-Spi-Version";
|
29
|
+
public static final String MANIFEST_PLUGIN_CLASS_PATH = "Embulk-Plugin-Class-Path";
|
27
30
|
|
28
31
|
private JarPluginLoader(final Manifest pluginManifest,
|
29
32
|
final Attributes pluginManifestAttributes,
|
@@ -44,7 +47,8 @@ public class JarPluginLoader
|
|
44
47
|
|
45
48
|
if (spiVersion == 0) {
|
46
49
|
final String mainClassName = getPluginMainClassNameFromManifest(manifestAttributes);
|
47
|
-
final
|
50
|
+
final List<String> pluginClassPath = getPluginClassPathFromManifest(manifestAttributes);
|
51
|
+
final Class mainClass = loadJarPluginMainClass(jarPath, mainClassName, pluginClassPath, classLoaderFactory);
|
48
52
|
return new JarPluginLoader(manifest, manifestAttributes, mainClass);
|
49
53
|
}
|
50
54
|
|
@@ -108,6 +112,7 @@ public class JarPluginLoader
|
|
108
112
|
|
109
113
|
private static Class loadJarPluginMainClass(final Path jarPath,
|
110
114
|
final String pluginMainClassName,
|
115
|
+
final List<String> pluginClassPath,
|
111
116
|
final PluginClassLoaderFactory pluginClassLoaderFactory)
|
112
117
|
throws InvalidJarPluginException
|
113
118
|
{
|
@@ -138,9 +143,15 @@ public class JarPluginLoader
|
|
138
143
|
throw new InvalidJarPluginException("JAR plugin path specified is invalid: " + jarPath.toString(), ex);
|
139
144
|
}
|
140
145
|
|
141
|
-
|
142
|
-
|
143
|
-
pluginClassLoaderFactory.
|
146
|
+
final PluginClassLoader pluginClassLoader;
|
147
|
+
if (pluginClassPath.isEmpty()) {
|
148
|
+
pluginClassLoader = pluginClassLoaderFactory.createForNestedJar(
|
149
|
+
JarPluginLoader.class.getClassLoader(), fileUrlJar);
|
150
|
+
}
|
151
|
+
else {
|
152
|
+
pluginClassLoader = pluginClassLoaderFactory.createForNestedJar(
|
153
|
+
JarPluginLoader.class.getClassLoader(), fileUrlJar, pluginClassPath);
|
154
|
+
}
|
144
155
|
|
145
156
|
final Class pluginMainClass;
|
146
157
|
try {
|
@@ -185,6 +196,22 @@ public class JarPluginLoader
|
|
185
196
|
return pluginMainClassName;
|
186
197
|
}
|
187
198
|
|
199
|
+
private static List<String> getPluginClassPathFromManifest(final Attributes manifestAttributes)
|
200
|
+
throws InvalidJarPluginException
|
201
|
+
{
|
202
|
+
final String pluginClassPathJoined = getAttributeFromManifest(manifestAttributes, MANIFEST_PLUGIN_CLASS_PATH);
|
203
|
+
|
204
|
+
if (pluginClassPathJoined == null) {
|
205
|
+
return Collections.<String>emptyList();
|
206
|
+
}
|
207
|
+
|
208
|
+
final List<String> pluginClassPath = new ArrayList<String>();
|
209
|
+
for (final String splitPluginClassPath : pluginClassPathJoined.split(" +", 0)) {
|
210
|
+
pluginClassPath.add(splitPluginClassPath);
|
211
|
+
}
|
212
|
+
return pluginClassPath;
|
213
|
+
}
|
214
|
+
|
188
215
|
private static String getAttributeFromManifest(final Attributes manifestAttributes, final String attributeName)
|
189
216
|
throws InvalidJarPluginException
|
190
217
|
{
|
@@ -20,7 +20,6 @@ import org.embulk.plugin.PluginType;
|
|
20
20
|
import org.embulk.plugin.PluginManager;
|
21
21
|
import org.embulk.spi.time.Timestamp;
|
22
22
|
import org.embulk.spi.time.TimestampFormatter;
|
23
|
-
import org.embulk.spi.time.TimestampFormatter.FormatterTask;
|
24
23
|
|
25
24
|
public class ExecSession
|
26
25
|
{
|
@@ -201,11 +200,7 @@ public class ExecSession
|
|
201
200
|
|
202
201
|
public TimestampFormatter newTimestampFormatter(String format, DateTimeZone timezone)
|
203
202
|
{
|
204
|
-
|
205
|
-
config.set("timezone", timezone.getID());
|
206
|
-
// TODO: Stop creating the |FormatterTask| as |TimestampFormater.FormatterTask| is deprecated since v0.6.14.
|
207
|
-
FormatterTask formatterTask = config.loadConfig(FormatterTask.class);
|
208
|
-
return new TimestampFormatter(format, formatterTask.getTimeZone());
|
203
|
+
return new TimestampFormatter(format, timezone);
|
209
204
|
}
|
210
205
|
|
211
206
|
public TempFileSpace getTempFileSpace()
|
@@ -13,9 +13,24 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
13
13
|
import org.jruby.util.ByteList;
|
14
14
|
import org.jcodings.specific.ASCIIEncoding;
|
15
15
|
|
16
|
+
@Deprecated
|
16
17
|
public class RubyValueApi
|
17
18
|
{
|
19
|
+
@Deprecated
|
18
20
|
public static Value fromMessagePack(RubyString content)
|
21
|
+
{
|
22
|
+
if (!fromMessagePackDeprecationWarned) {
|
23
|
+
System.err.println("[WARN] Plugin uses deprecated org.embulk.spi.json.RubyValueApi.fromMessagePack");
|
24
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/802");
|
25
|
+
// The |fromMessagePackDeprecationWarned| flag is used only for warning messages.
|
26
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
27
|
+
fromMessagePackDeprecationWarned = true;
|
28
|
+
}
|
29
|
+
|
30
|
+
return fromMessagePackInternal(content);
|
31
|
+
}
|
32
|
+
|
33
|
+
private static Value fromMessagePackInternal(RubyString content)
|
19
34
|
{
|
20
35
|
ByteList list = content.getByteList();
|
21
36
|
try {
|
@@ -40,8 +55,17 @@ public class RubyValueApi
|
|
40
55
|
}
|
41
56
|
}
|
42
57
|
|
58
|
+
@Deprecated
|
43
59
|
public static RubyString toMessagePack(Ruby runtime, Value value)
|
44
60
|
{
|
61
|
+
if (!toMessagePackDeprecationWarned) {
|
62
|
+
System.err.println("[WARN] Plugin uses deprecated org.embulk.spi.json.RubyValueApi.toMessagePack");
|
63
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/802");
|
64
|
+
// The |toMessagePackDeprecationWarned| flag is used only for warning messages.
|
65
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
66
|
+
toMessagePackDeprecationWarned = true;
|
67
|
+
}
|
68
|
+
|
45
69
|
try {
|
46
70
|
MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
|
47
71
|
packer.packValue(value);
|
@@ -54,9 +78,23 @@ public class RubyValueApi
|
|
54
78
|
}
|
55
79
|
}
|
56
80
|
|
81
|
+
@Deprecated
|
57
82
|
public static Value toValue(Ruby runtime, IRubyObject object)
|
58
83
|
{
|
84
|
+
if (!toValueDeprecationWarned) {
|
85
|
+
System.err.println("[WARN] Plugin uses deprecated org.embulk.spi.json.RubyValueApi.toValue");
|
86
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/802");
|
87
|
+
// The |toValueDeprecationWarned| flag is used only for warning messages.
|
88
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
89
|
+
toValueDeprecationWarned = true;
|
90
|
+
}
|
91
|
+
|
59
92
|
RubyString string = (RubyString) object.callMethod(runtime.getCurrentContext(), "to_msgpack");
|
60
|
-
return
|
93
|
+
return fromMessagePackInternal(string);
|
61
94
|
}
|
95
|
+
|
96
|
+
private static boolean fromMessagePackDeprecationWarned = false;
|
97
|
+
private static boolean toMessagePackDeprecationWarned = false;
|
98
|
+
private static boolean toValueDeprecationWarned = false;
|
99
|
+
|
62
100
|
}
|
@@ -88,15 +88,33 @@ public class Timestamp
|
|
88
88
|
}
|
89
89
|
}
|
90
90
|
|
91
|
+
@Deprecated
|
91
92
|
public RubyTime getRubyTime(Ruby runtime)
|
92
93
|
{
|
94
|
+
if (!getRubyTimeDeprecationWarned) {
|
95
|
+
System.err.println("[WARN] Plugin uses deprecated org.embulk.spi.time.Timestamp.getRubyTime");
|
96
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/820");
|
97
|
+
// The |getRubyTimeDeprecationWarned| flag is used only for warning messages.
|
98
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
99
|
+
getRubyTimeDeprecationWarned = true;
|
100
|
+
}
|
101
|
+
|
93
102
|
RubyTime time = new RubyTime(runtime, runtime.getClass("Time"), new DateTime(toEpochMilli())).gmtime();
|
94
103
|
time.setNSec(nano % 1000000);
|
95
104
|
return time;
|
96
105
|
}
|
97
106
|
|
107
|
+
@Deprecated
|
98
108
|
public static Timestamp fromRubyTime(RubyTime time)
|
99
109
|
{
|
110
|
+
if (!fromRubyTimeDeprecationWarned) {
|
111
|
+
System.err.println("[WARN] Plugin uses deprecated org.embulk.spi.time.Timestamp.fromRubyTime");
|
112
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/820");
|
113
|
+
// The |fromRubyTimeDeprecationWarned| flag is used only for warning messages.
|
114
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
115
|
+
fromRubyTimeDeprecationWarned = true;
|
116
|
+
}
|
117
|
+
|
100
118
|
long msec = time.getDateTime().getMillis();
|
101
119
|
long sec = msec / 1000;
|
102
120
|
long nsec = time.getNSec() + (msec % 1000) * 1000000;
|
@@ -156,4 +174,7 @@ public class Timestamp
|
|
156
174
|
|
157
175
|
return new Timestamp(seconds, nano);
|
158
176
|
}
|
177
|
+
|
178
|
+
private static boolean getRubyTimeDeprecationWarned = false;
|
179
|
+
private static boolean fromRubyTimeDeprecationWarned = false;
|
159
180
|
}
|
@@ -26,12 +26,30 @@ public class TimestampFormat
|
|
26
26
|
@Deprecated
|
27
27
|
public TimestampFormatter newFormatter(TimestampFormatter.FormatterTask task)
|
28
28
|
{
|
29
|
+
// NOTE: Its deprecation is not actually from ScriptingContainer, though.
|
30
|
+
// TODO: Notify users about deprecated calls through the notification reporter.
|
31
|
+
if (!newFormatterDeprecationWarned) {
|
32
|
+
System.err.println("[WARN] Plugin uses deprecated method org.embulk.spi.time.TimestampFormat.newFormatter");
|
33
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/828");
|
34
|
+
// The |newFormatterDeprecationWarned| flag is used only for warning messages.
|
35
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
36
|
+
newFormatterDeprecationWarned = true;
|
37
|
+
}
|
29
38
|
return new TimestampFormatter(format, task.getTimeZone());
|
30
39
|
}
|
31
40
|
|
32
41
|
@Deprecated
|
33
42
|
public TimestampParser newParser(TimestampParser.ParserTask task)
|
34
43
|
{
|
44
|
+
// NOTE: Its deprecation is not actually from ScriptingContainer, though.
|
45
|
+
// TODO: Notify users about deprecated calls through the notification reporter.
|
46
|
+
if (!newParserDeprecationWarned) {
|
47
|
+
System.err.println("[WARN] Plugin uses deprecated method org.embulk.spi.time.TimestampFormat.newParser");
|
48
|
+
System.err.println("[WARN] Report plugins in your config at: https://github.com/embulk/embulk/issues/828");
|
49
|
+
// The |newParserDeprecationWarned| flag is used only for warning messages.
|
50
|
+
// Even in case of race conditions, messages are just duplicated -- should be acceptable.
|
51
|
+
newParserDeprecationWarned = true;
|
52
|
+
}
|
35
53
|
return new TimestampParser(format, task.getDefaultTimeZone());
|
36
54
|
}
|
37
55
|
|
@@ -69,6 +87,9 @@ public class TimestampFormat
|
|
69
87
|
}
|
70
88
|
}
|
71
89
|
|
90
|
+
private static boolean newFormatterDeprecationWarned = false;
|
91
|
+
private static boolean newParserDeprecationWarned = false;
|
92
|
+
|
72
93
|
//// Java standard TimeZone
|
73
94
|
//static TimeZone parseDateTimeZone(String s)
|
74
95
|
//{
|
@@ -24,17 +24,34 @@ import org.embulk.spi.Column;
|
|
24
24
|
import org.embulk.spi.PageBuilder;
|
25
25
|
import org.embulk.config.ConfigException;
|
26
26
|
|
27
|
-
|
27
|
+
class DynamicColumnSetterFactory
|
28
28
|
{
|
29
29
|
private final DefaultValueSetter defaultValue;
|
30
30
|
private final DynamicPageBuilder.BuilderTask task;
|
31
|
+
private final boolean useColumnForTimestampMetadata;
|
31
32
|
|
32
|
-
DynamicColumnSetterFactory(
|
33
|
-
DynamicPageBuilder.BuilderTask task,
|
34
|
-
DefaultValueSetter defaultValue
|
33
|
+
private DynamicColumnSetterFactory(
|
34
|
+
final DynamicPageBuilder.BuilderTask task,
|
35
|
+
final DefaultValueSetter defaultValue,
|
36
|
+
final boolean useColumnForTimestampMetadata)
|
35
37
|
{
|
36
38
|
this.defaultValue = defaultValue;
|
37
39
|
this.task = task;
|
40
|
+
this.useColumnForTimestampMetadata = useColumnForTimestampMetadata;
|
41
|
+
}
|
42
|
+
|
43
|
+
static DynamicColumnSetterFactory createWithTimestampMetadataFromBuilderTask(
|
44
|
+
final DynamicPageBuilder.BuilderTask task,
|
45
|
+
final DefaultValueSetter defaultValue)
|
46
|
+
{
|
47
|
+
return new DynamicColumnSetterFactory(task, defaultValue, false);
|
48
|
+
}
|
49
|
+
|
50
|
+
static DynamicColumnSetterFactory createWithTimestampMetadataFromColumn(
|
51
|
+
final DynamicPageBuilder.BuilderTask task,
|
52
|
+
final DefaultValueSetter defaultValue)
|
53
|
+
{
|
54
|
+
return new DynamicColumnSetterFactory(task, defaultValue, true);
|
38
55
|
}
|
39
56
|
|
40
57
|
public static DefaultValueSetter nullDefaultValue()
|
@@ -53,22 +70,29 @@ public class DynamicColumnSetterFactory
|
|
53
70
|
return new DoubleColumnSetter(pageBuilder, column, defaultValue);
|
54
71
|
} else if (type instanceof StringType) {
|
55
72
|
TimestampFormatter formatter = new TimestampFormatter(
|
56
|
-
|
73
|
+
getTimestampFormatForFormatter(column).getFormat(), getTimeZone(column));
|
57
74
|
return new StringColumnSetter(pageBuilder, column, defaultValue, formatter);
|
58
75
|
} else if (type instanceof TimestampType) {
|
59
76
|
// TODO use flexible time format like Ruby's Time.parse
|
60
|
-
TimestampParser parser
|
61
|
-
|
77
|
+
final TimestampParser parser;
|
78
|
+
if (this.useColumnForTimestampMetadata) {
|
79
|
+
final TimestampType timestampType = (TimestampType) type;
|
80
|
+
parser = new TimestampParser(timestampType.getFormat(), getTimeZone(column));
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
parser = new TimestampParser(
|
84
|
+
getTimestampFormatForParser(column).getFormat(), getTimeZone(column));
|
85
|
+
}
|
62
86
|
return new TimestampColumnSetter(pageBuilder, column, defaultValue, parser);
|
63
87
|
} else if (type instanceof JsonType) {
|
64
88
|
TimestampFormatter formatter = new TimestampFormatter(
|
65
|
-
|
89
|
+
getTimestampFormatForFormatter(column).getFormat(), getTimeZone(column));
|
66
90
|
return new JsonColumnSetter(pageBuilder, column, defaultValue, formatter);
|
67
91
|
}
|
68
92
|
throw new ConfigException("Unknown column type: "+type);
|
69
93
|
}
|
70
94
|
|
71
|
-
private TimestampFormat
|
95
|
+
private TimestampFormat getTimestampFormatForFormatter(Column column)
|
72
96
|
{
|
73
97
|
DynamicPageBuilder.ColumnOption option = getColumnOption(column);
|
74
98
|
if (option != null) {
|
@@ -78,6 +102,16 @@ public class DynamicColumnSetterFactory
|
|
78
102
|
}
|
79
103
|
}
|
80
104
|
|
105
|
+
private TimestampFormat getTimestampFormatForParser(Column column)
|
106
|
+
{
|
107
|
+
DynamicPageBuilder.ColumnOption option = getColumnOption(column);
|
108
|
+
if (option != null) {
|
109
|
+
return option.getTimestampFormat();
|
110
|
+
} else {
|
111
|
+
return new TimestampFormat("%Y-%m-%d %H:%M:%S.%N");
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
81
115
|
private DateTimeZone getTimeZone(Column column)
|
82
116
|
{
|
83
117
|
DynamicPageBuilder.ColumnOption option = getColumnOption(column);
|
@@ -50,8 +50,10 @@ public class DynamicPageBuilder
|
|
50
50
|
public static interface ColumnOption
|
51
51
|
extends Task
|
52
52
|
{
|
53
|
+
// DynamicPageBuilder is used for inputs, then datetime parsing.
|
54
|
+
// Ruby's strptime does not accept numeric prefixes in specifiers such as "%6N".
|
53
55
|
@Config("timestamp_format")
|
54
|
-
@ConfigDefault("\"%Y-%m-%d %H:%M:%S.%
|
56
|
+
@ConfigDefault("\"%Y-%m-%d %H:%M:%S.%N\"")
|
55
57
|
public TimestampFormat getTimestampFormat();
|
56
58
|
|
57
59
|
@Config("timezone")
|
@@ -59,16 +61,14 @@ public class DynamicPageBuilder
|
|
59
61
|
public Optional<DateTimeZone> getTimeZone();
|
60
62
|
}
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
private DynamicPageBuilder(
|
65
|
+
final DynamicColumnSetterFactory factory,
|
66
|
+
final BufferAllocator allocator,
|
67
|
+
final Schema schema,
|
68
|
+
final PageOutput output)
|
64
69
|
{
|
65
70
|
this.pageBuilder = new PageBuilder(allocator, schema, output);
|
66
71
|
this.schema = schema;
|
67
|
-
|
68
|
-
// TODO configurable default value
|
69
|
-
DynamicColumnSetterFactory factory = new DynamicColumnSetterFactory(task,
|
70
|
-
DynamicColumnSetterFactory.nullDefaultValue());
|
71
|
-
|
72
72
|
ImmutableList.Builder<DynamicColumnSetter> setters = ImmutableList.builder();
|
73
73
|
ImmutableMap.Builder<String, DynamicColumnSetter> lookup = ImmutableMap.builder();
|
74
74
|
for (Column c : schema.getColumns()) {
|
@@ -80,6 +80,44 @@ public class DynamicPageBuilder
|
|
80
80
|
this.columnLookup = lookup.build();
|
81
81
|
}
|
82
82
|
|
83
|
+
@Deprecated // The static creator method "createWithTimestampMetadataFromBuilderTask" is preferred.
|
84
|
+
public DynamicPageBuilder(
|
85
|
+
BuilderTask task,
|
86
|
+
BufferAllocator allocator,
|
87
|
+
Schema schema,
|
88
|
+
PageOutput output)
|
89
|
+
{
|
90
|
+
this(DynamicColumnSetterFactory.createWithTimestampMetadataFromBuilderTask(
|
91
|
+
task, DynamicColumnSetterFactory.nullDefaultValue()), // TODO configurable default value
|
92
|
+
allocator,
|
93
|
+
schema,
|
94
|
+
output);
|
95
|
+
}
|
96
|
+
|
97
|
+
public static DynamicPageBuilder createWithTimestampMetadataFromBuilderTask(
|
98
|
+
BuilderTask task,
|
99
|
+
BufferAllocator allocator,
|
100
|
+
Schema schema,
|
101
|
+
PageOutput output)
|
102
|
+
{
|
103
|
+
// TODO configurable default value
|
104
|
+
DynamicColumnSetterFactory factory = DynamicColumnSetterFactory.createWithTimestampMetadataFromBuilderTask(
|
105
|
+
task, DynamicColumnSetterFactory.nullDefaultValue());
|
106
|
+
return new DynamicPageBuilder(factory, allocator, schema, output);
|
107
|
+
}
|
108
|
+
|
109
|
+
public static DynamicPageBuilder createWithTimestampMetadataFromColumn(
|
110
|
+
BuilderTask task,
|
111
|
+
BufferAllocator allocator,
|
112
|
+
Schema schema,
|
113
|
+
PageOutput output)
|
114
|
+
{
|
115
|
+
// TODO configurable default value
|
116
|
+
DynamicColumnSetterFactory factory = DynamicColumnSetterFactory.createWithTimestampMetadataFromColumn(
|
117
|
+
task, DynamicColumnSetterFactory.nullDefaultValue());
|
118
|
+
return new DynamicPageBuilder(factory, allocator, schema, output);
|
119
|
+
}
|
120
|
+
|
83
121
|
public List<Column> getColumns()
|
84
122
|
{
|
85
123
|
return schema.getColumns();
|