embulk 0.8.18-java → 0.8.19-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 +10 -0
- data/build.gradle +10 -3
- data/embulk-cli/build.gradle +2 -0
- data/embulk-cli/src/main/bat/selfrun.bat +98 -0
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkExample.java +82 -0
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkMigrate.java +458 -0
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkNew.java +419 -0
- data/embulk-cli/src/main/java/org/embulk/cli/EmbulkSelfUpdate.java +248 -0
- data/embulk-cli/src/main/sh/selfrun.sh +0 -103
- data/embulk-cli/src/test/java/org/embulk/cli/SelfrunTest.java +158 -143
- data/embulk-core/build.gradle +2 -2
- data/embulk-core/src/main/java/org/embulk/EmbulkVersion.java +109 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +11 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +29 -3
- data/embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java +47 -13
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +6 -3
- data/embulk-core/src/main/java/org/embulk/spi/PageBuilder.java +385 -64
- data/embulk-core/src/main/java/org/embulk/spi/TempFileSpace.java +2 -1
- data/embulk-core/src/test/java/org/embulk/spi/TestPageBuilderReader.java +62 -0
- data/embulk-docs/src/built-in.rst +59 -21
- data/embulk-docs/src/customization.rst +8 -8
- data/embulk-docs/src/developers/index.rst +45 -0
- data/embulk-docs/src/index.rst +11 -7
- data/embulk-docs/src/recipe.rst +1 -1
- data/embulk-docs/src/recipe/{scheduled-csv-load-to-elasticsearch-kibana4.rst → scheduled-csv-load-to-elasticsearch-kibana5.rst} +26 -24
- data/embulk-docs/src/release.rst +1 -0
- data/embulk-docs/src/release/release-0.4.0.rst +1 -1
- data/embulk-docs/src/release/release-0.5.0.rst +1 -1
- data/embulk-docs/src/release/release-0.6.0.rst +1 -1
- data/embulk-docs/src/release/release-0.6.20.rst +1 -1
- data/embulk-docs/src/release/release-0.8.19.rst +43 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +2 -2
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +30 -1
- data/embulk-standards/src/test/java/org/embulk/standards/guess/TestCsvGuessPlugin.java +10 -0
- data/embulk-standards/src/test/java/org/embulk/standards/preview/TestFilePreview.java +73 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/guess/csv/test/test_skip_suggest_if_empty_sample_records.csv +5 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/guess/csv/test/test_skip_suggest_if_empty_sample_records_guessed.yml +2 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/guess/csv/test/test_skip_suggest_if_empty_sample_records_seed.yml +1 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_sample_buffer_bytes.csv +5 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_sample_buffer_bytes_exec.yml +1 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_sample_buffer_bytes_load.yml +19 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_sample_buffer_bytes_previewed.csv +1 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_simple.csv +5 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_simple_load.yml +19 -0
- data/embulk-standards/src/test/resources/org/embulk/standards/preview/file/test/test_simple_previewed.csv +4 -0
- data/embulk-test/src/main/java/org/embulk/test/PreviewResultInputPlugin.java +65 -0
- data/embulk-test/src/main/java/org/embulk/test/TestingBulkLoader.java +5 -0
- data/embulk-test/src/main/java/org/embulk/test/TestingEmbulk.java +59 -2
- data/embulk.gemspec +2 -1
- data/lib/embulk/command/embulk_run.rb +11 -49
- data/lib/embulk/data/new/README.md.vm +106 -0
- data/lib/embulk/data/new/{gitignore.erb → gitignore.vm} +3 -3
- data/lib/embulk/data/new/java/{build.gradle.erb → build.gradle.vm} +8 -8
- data/lib/embulk/data/new/java/{decoder.java.erb → decoder.java.vm} +6 -4
- data/lib/embulk/data/new/java/{encoder.java.erb → encoder.java.vm} +7 -5
- data/lib/embulk/data/new/java/{file_input.java.erb → file_input.java.vm} +9 -7
- data/lib/embulk/data/new/java/{file_output.java.erb → file_output.java.vm} +7 -5
- data/lib/embulk/data/new/java/{filter.java.erb → filter.java.vm} +4 -3
- data/lib/embulk/data/new/java/{formatter.java.erb → formatter.java.vm} +5 -4
- data/lib/embulk/data/new/java/{input.java.erb → input.java.vm} +6 -4
- data/lib/embulk/data/new/java/{output.java.erb → output.java.vm} +7 -5
- data/lib/embulk/data/new/java/{parser.java.erb → parser.java.vm} +5 -4
- data/lib/embulk/data/new/java/plugin_loader.rb.vm +3 -0
- data/lib/embulk/data/new/java/test.java.vm +5 -0
- data/lib/embulk/data/new/ruby/decoder_guess.rb.vm +25 -0
- data/lib/embulk/data/new/ruby/{filter.rb.erb → filter.rb.vm} +2 -2
- data/lib/embulk/data/new/ruby/{formatter.rb.erb → formatter.rb.vm} +2 -2
- data/lib/embulk/data/new/ruby/gemspec.vm +20 -0
- data/lib/embulk/data/new/ruby/{input.rb.erb → input.rb.vm} +10 -10
- data/lib/embulk/data/new/ruby/{output.rb.erb → output.rb.vm} +7 -7
- data/lib/embulk/data/new/ruby/{parser.rb.erb → parser.rb.vm} +2 -2
- data/lib/embulk/data/new/ruby/parser_guess.rb.vm +65 -0
- data/lib/embulk/guess/csv.rb +5 -0
- data/lib/embulk/version.rb +22 -1
- metadata +55 -35
- data/lib/embulk/command/embulk_example.rb +0 -33
- data/lib/embulk/command/embulk_generate_bin.rb +0 -62
- data/lib/embulk/command/embulk_migrate_plugin.rb +0 -244
- data/lib/embulk/command/embulk_new_plugin.rb +0 -126
- data/lib/embulk/command/embulk_selfupdate.rb +0 -121
- data/lib/embulk/data/new/README.md.erb +0 -111
- data/lib/embulk/data/new/java/plugin_loader.rb.erb +0 -3
- data/lib/embulk/data/new/java/test.java.erb +0 -5
- data/lib/embulk/data/new/ruby/decoder_guess.rb.erb +0 -25
- data/lib/embulk/data/new/ruby/gemspec.erb +0 -20
- data/lib/embulk/data/new/ruby/parser_guess.rb.erb +0 -65
data/embulk-core/build.gradle
CHANGED
@@ -31,7 +31,7 @@ dependencies {
|
|
31
31
|
compile 'org.slf4j:slf4j-api:1.7.12'
|
32
32
|
compile 'org.jruby:jruby-complete:' + project.jrubyVersion
|
33
33
|
compile 'com.google.code.findbugs:annotations:3.0.0'
|
34
|
-
compile 'org.yaml:snakeyaml:1.
|
34
|
+
compile 'org.yaml:snakeyaml:1.18'
|
35
35
|
compile 'javax.validation:validation-api:1.1.0.Final'
|
36
36
|
compile 'org.apache.bval:bval-jsr303:0.5'
|
37
37
|
compile 'io.airlift:slice:0.9'
|
@@ -45,7 +45,7 @@ dependencies {
|
|
45
45
|
|
46
46
|
gems 'rubygems:bundler:1.10.6'
|
47
47
|
gems 'rubygems:msgpack:1.1.0'
|
48
|
-
gems 'rubygems:liquid:
|
48
|
+
gems 'rubygems:liquid:4.0.0'
|
49
49
|
}
|
50
50
|
|
51
51
|
task unpackGems(type: JRubyPrepare) {
|
@@ -0,0 +1,109 @@
|
|
1
|
+
package org.embulk;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.net.URL;
|
5
|
+
import java.security.CodeSource;
|
6
|
+
import java.security.ProtectionDomain;
|
7
|
+
import java.util.jar.Attributes;
|
8
|
+
import java.util.jar.JarFile;
|
9
|
+
import java.util.jar.Manifest;
|
10
|
+
|
11
|
+
public final class EmbulkVersion
|
12
|
+
{
|
13
|
+
private EmbulkVersion()
|
14
|
+
{
|
15
|
+
}
|
16
|
+
|
17
|
+
// Expecting Embulk is always packaged in the embulk-cli jar whenever the Embulk version is checked in Java.
|
18
|
+
static {
|
19
|
+
VERSION = getImplementationVersion(getSelfJarManifest(), "[embulk-version-unavailable]");
|
20
|
+
}
|
21
|
+
|
22
|
+
private static Manifest getSelfJarManifest()
|
23
|
+
{
|
24
|
+
try {
|
25
|
+
final ProtectionDomain protectionDomain;
|
26
|
+
try {
|
27
|
+
protectionDomain = EmbulkVersion.class.getProtectionDomain();
|
28
|
+
}
|
29
|
+
catch (SecurityException ex) {
|
30
|
+
System.err.println("Embulk version unavailable due to ProtectionDomain inaccessible.");
|
31
|
+
ex.printStackTrace();
|
32
|
+
return null;
|
33
|
+
}
|
34
|
+
|
35
|
+
final CodeSource codeSource = protectionDomain.getCodeSource();
|
36
|
+
if (codeSource == null) {
|
37
|
+
System.err.println("Embulk version unavailable due to CodeSource unavailable.");
|
38
|
+
return null;
|
39
|
+
}
|
40
|
+
|
41
|
+
final URL selfJarUrl = codeSource.getLocation();
|
42
|
+
if (selfJarUrl == null) {
|
43
|
+
System.err.println("Embulk version unavailable due to the location of CodeSource unavailable.");
|
44
|
+
return null;
|
45
|
+
}
|
46
|
+
else if (!selfJarUrl.getProtocol().equals("file")) {
|
47
|
+
System.err.println("Embulk version unavailable as the location of CodeSource is not local.");
|
48
|
+
return null;
|
49
|
+
}
|
50
|
+
|
51
|
+
final String selfJarPathString = selfJarUrl.getPath();
|
52
|
+
if (selfJarPathString == null) {
|
53
|
+
System.err.println("Embulk version unavailable due to the path of CodeSource unavailable.");
|
54
|
+
return null;
|
55
|
+
}
|
56
|
+
else if (selfJarPathString.isEmpty()) {
|
57
|
+
System.err.println("Embulk version unavailable due to the path of CodeSource empty.");
|
58
|
+
return null;
|
59
|
+
}
|
60
|
+
|
61
|
+
try (final JarFile selfJarFile = new JarFile(selfJarPathString)) {
|
62
|
+
try {
|
63
|
+
return selfJarFile.getManifest();
|
64
|
+
}
|
65
|
+
catch (IllegalStateException ex) {
|
66
|
+
System.err.println("Embulk version unavailable due to the jar file closed unexpectedly.");
|
67
|
+
ex.printStackTrace();
|
68
|
+
return null;
|
69
|
+
}
|
70
|
+
catch (IOException ex) {
|
71
|
+
System.err.println("Embulk version unavailable due to failure to get the manifst in the jar file.");
|
72
|
+
ex.printStackTrace();
|
73
|
+
return null;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
catch (SecurityException ex) {
|
77
|
+
System.err.println("Embulk version unavailable due to the jar file inaccessible.");
|
78
|
+
ex.printStackTrace();
|
79
|
+
return null;
|
80
|
+
}
|
81
|
+
catch (IOException ex) {
|
82
|
+
System.err.println("Embulk version unavailable due to failure to access the jar file.");
|
83
|
+
ex.printStackTrace();
|
84
|
+
return null;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
catch (Throwable ex) {
|
88
|
+
System.err.println("Embulk version unavailable due to an unknown exception.");
|
89
|
+
ex.printStackTrace();
|
90
|
+
return null;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
private static String getImplementationVersion(final Manifest manifest, final String defaultVersion)
|
95
|
+
{
|
96
|
+
if (manifest == null) {
|
97
|
+
return defaultVersion;
|
98
|
+
}
|
99
|
+
final Attributes mainAttributes = manifest.getMainAttributes();
|
100
|
+
final String implementationVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
101
|
+
if (implementationVersion == null) {
|
102
|
+
System.err.println("Embulk version unavailable due to the manifest not containing Implementation-Version.");
|
103
|
+
return defaultVersion;
|
104
|
+
}
|
105
|
+
return implementationVersion;
|
106
|
+
}
|
107
|
+
|
108
|
+
public static final String VERSION;
|
109
|
+
}
|
@@ -55,6 +55,10 @@ public class GuessExecutor
|
|
55
55
|
@Config("exclude_guess_plugins")
|
56
56
|
@ConfigDefault("[]")
|
57
57
|
public List<PluginType> getExcludeGuessPlugins();
|
58
|
+
|
59
|
+
@Config("guess_sample_buffer_bytes")
|
60
|
+
@ConfigDefault("32768") // 32 * 1024
|
61
|
+
public int getSampleBufferBytes();
|
58
62
|
}
|
59
63
|
|
60
64
|
public static void registerDefaultGuessPluginTo(Binder binder, PluginType type)
|
@@ -63,6 +67,13 @@ public class GuessExecutor
|
|
63
67
|
multibinder.addBinding().toInstance(type);
|
64
68
|
}
|
65
69
|
|
70
|
+
// Used by FileInputRunner#guess(..)
|
71
|
+
public static ConfigSource createSampleBufferConfigFromExecConfig(ConfigSource execConfig)
|
72
|
+
{
|
73
|
+
final GuessExecutorTask execTask = execConfig.loadConfig(GuessExecutorTask.class);
|
74
|
+
return Exec.newConfigSource().set("sample_buffer_bytes", execTask.getSampleBufferBytes());
|
75
|
+
}
|
76
|
+
|
66
77
|
@Inject
|
67
78
|
public GuessExecutor(@ForSystemConfig ConfigSource systemConfig,
|
68
79
|
@ForGuess Set<PluginType> defaultGuessPlugins)
|
@@ -12,9 +12,9 @@ import org.embulk.config.Task;
|
|
12
12
|
import org.embulk.config.TaskSource;
|
13
13
|
import org.embulk.config.ConfigSource;
|
14
14
|
import org.embulk.config.TaskReport;
|
15
|
+
import org.embulk.exec.SamplingParserPlugin.SampleBufferTask;
|
15
16
|
import org.embulk.plugin.PluginType;
|
16
17
|
import org.embulk.spi.Buffer;
|
17
|
-
import org.embulk.spi.FileInputPlugin;
|
18
18
|
import org.embulk.spi.FileInputRunner;
|
19
19
|
import org.embulk.spi.Schema;
|
20
20
|
import org.embulk.spi.Page;
|
@@ -26,6 +26,7 @@ import org.embulk.spi.Exec;
|
|
26
26
|
import org.embulk.spi.ExecSession;
|
27
27
|
import org.embulk.spi.ExecAction;
|
28
28
|
import org.embulk.spi.util.Filters;
|
29
|
+
import org.slf4j.Logger;
|
29
30
|
|
30
31
|
public class PreviewExecutor
|
31
32
|
{
|
@@ -35,6 +36,10 @@ public class PreviewExecutor
|
|
35
36
|
public interface PreviewTask
|
36
37
|
extends Task
|
37
38
|
{
|
39
|
+
@Config("exec")
|
40
|
+
@ConfigDefault("{}")
|
41
|
+
public ConfigSource getExecConfig();
|
42
|
+
|
38
43
|
@Config("in")
|
39
44
|
@NotNull
|
40
45
|
public ConfigSource getInputConfig();
|
@@ -52,6 +57,14 @@ public class PreviewExecutor
|
|
52
57
|
public void setInputTask(TaskSource taskSource);
|
53
58
|
}
|
54
59
|
|
60
|
+
public interface PreviewExecutorTask
|
61
|
+
extends Task
|
62
|
+
{
|
63
|
+
@Config("preview_sample_buffer_bytes")
|
64
|
+
@ConfigDefault("32768") // 32 * 1024
|
65
|
+
public int getSampleBufferBytes();
|
66
|
+
}
|
67
|
+
|
55
68
|
@Inject
|
56
69
|
public PreviewExecutor(Injector injector,
|
57
70
|
@ForSystemConfig ConfigSource systemConfig)
|
@@ -93,7 +106,7 @@ public class PreviewExecutor
|
|
93
106
|
List<FilterPlugin> filterPlugins = newFilterPlugins(task);
|
94
107
|
|
95
108
|
if (inputPlugin instanceof FileInputRunner) { // file input runner
|
96
|
-
Buffer sample = SamplingParserPlugin.runFileInputSampling((FileInputRunner)inputPlugin, config.getNested("in"));
|
109
|
+
Buffer sample = SamplingParserPlugin.runFileInputSampling((FileInputRunner)inputPlugin, config.getNested("in"), createSampleBufferConfigFromExecConfig(config.getNested("exec")));
|
97
110
|
FileInputRunner previewRunner = new FileInputRunner(new BufferFileInputPlugin(sample));
|
98
111
|
return doPreview(task, previewRunner, filterPlugins);
|
99
112
|
}
|
@@ -102,6 +115,12 @@ public class PreviewExecutor
|
|
102
115
|
}
|
103
116
|
}
|
104
117
|
|
118
|
+
private static ConfigSource createSampleBufferConfigFromExecConfig(ConfigSource execConfig)
|
119
|
+
{
|
120
|
+
final PreviewExecutorTask execTask = execConfig.loadConfig(PreviewExecutorTask.class);
|
121
|
+
return Exec.newConfigSource().set("sample_buffer_bytes", execTask.getSampleBufferBytes());
|
122
|
+
}
|
123
|
+
|
105
124
|
private PreviewResult doPreview(final PreviewTask task, final InputPlugin input, final List<FilterPlugin> filterPlugins)
|
106
125
|
{
|
107
126
|
try {
|
@@ -144,16 +163,19 @@ public class PreviewExecutor
|
|
144
163
|
private static class SamplingPageOutput
|
145
164
|
implements PageOutput
|
146
165
|
{
|
166
|
+
private final Logger log = Exec.getLogger(this.getClass());
|
147
167
|
private final int sampleRows;
|
148
168
|
private final Schema schema;
|
149
169
|
private List<Page> pages;
|
150
170
|
private int recordCount;
|
171
|
+
private PreviewResult res;
|
151
172
|
|
152
173
|
public SamplingPageOutput(int sampleRows, Schema schema)
|
153
174
|
{
|
154
175
|
this.sampleRows = sampleRows;
|
155
176
|
this.schema = schema;
|
156
177
|
this.pages = new ArrayList<Page>();
|
178
|
+
this.res = null;
|
157
179
|
}
|
158
180
|
|
159
181
|
public int getRecordCount()
|
@@ -174,10 +196,14 @@ public class PreviewExecutor
|
|
174
196
|
@Override
|
175
197
|
public void finish()
|
176
198
|
{
|
199
|
+
if (res != null) {
|
200
|
+
log.error("PreviewResult recreation will cause a bug. The plugin must call PageOutput#finish() only once.");
|
201
|
+
}
|
202
|
+
|
177
203
|
if (recordCount == 0) {
|
178
204
|
throw new NoSampleException("No input records to preview");
|
179
205
|
}
|
180
|
-
|
206
|
+
res = new PreviewResult(schema, pages);
|
181
207
|
pages = null;
|
182
208
|
throw new PreviewedNoticeError(res);
|
183
209
|
}
|
@@ -1,8 +1,13 @@
|
|
1
1
|
package org.embulk.exec;
|
2
2
|
|
3
|
+
import java.text.NumberFormat;
|
3
4
|
import java.util.List;
|
5
|
+
|
4
6
|
import com.google.inject.Inject;
|
5
7
|
import com.google.common.base.Preconditions;
|
8
|
+
import org.embulk.config.Config;
|
9
|
+
import org.embulk.config.ConfigDefault;
|
10
|
+
import org.embulk.config.Task;
|
6
11
|
import org.embulk.config.TaskSource;
|
7
12
|
import org.embulk.config.ConfigSource;
|
8
13
|
import org.embulk.config.TaskReport;
|
@@ -15,6 +20,9 @@ import org.embulk.spi.ParserPlugin;
|
|
15
20
|
import org.embulk.spi.FileInput;
|
16
21
|
import org.embulk.spi.FileInputRunner;
|
17
22
|
import org.embulk.spi.PageOutput;
|
23
|
+
import org.slf4j.Logger;
|
24
|
+
|
25
|
+
import static java.util.Locale.ENGLISH;
|
18
26
|
import static org.embulk.spi.util.Inputs.each;
|
19
27
|
|
20
28
|
/*
|
@@ -25,9 +33,18 @@ public class SamplingParserPlugin
|
|
25
33
|
{
|
26
34
|
public static Buffer runFileInputSampling(final FileInputRunner runner, ConfigSource inputConfig)
|
27
35
|
{
|
36
|
+
return runFileInputSampling(runner, inputConfig, Exec.newConfigSource());
|
37
|
+
}
|
38
|
+
|
39
|
+
public static Buffer runFileInputSampling(final FileInputRunner runner, ConfigSource inputConfig, ConfigSource sampleBufferConfig)
|
40
|
+
{
|
41
|
+
final SampleBufferTask sampleBufferTask = sampleBufferConfig.loadConfig(SampleBufferTask.class);
|
42
|
+
|
28
43
|
// override in.parser.type so that FileInputRunner creates SamplingParserPlugin
|
29
44
|
ConfigSource samplingInputConfig = inputConfig.deepCopy();
|
30
|
-
samplingInputConfig.getNestedOrSetEmpty("parser")
|
45
|
+
samplingInputConfig.getNestedOrSetEmpty("parser")
|
46
|
+
.set("type", "system_sampling")
|
47
|
+
.set("sample_buffer_bytes", sampleBufferTask.getSampleBufferBytes());
|
31
48
|
samplingInputConfig.set("decoders", null);
|
32
49
|
|
33
50
|
try {
|
@@ -120,42 +137,59 @@ public class SamplingParserPlugin
|
|
120
137
|
}
|
121
138
|
}
|
122
139
|
|
123
|
-
private final
|
124
|
-
private final
|
140
|
+
private final NumberFormat numberFormat = NumberFormat.getNumberInstance(ENGLISH);
|
141
|
+
private final Logger log = Exec.getLogger(this.getClass());
|
142
|
+
private final int minSampleBufferBytes;
|
143
|
+
|
144
|
+
public interface PluginTask
|
145
|
+
extends Task, SampleBufferTask
|
146
|
+
{
|
147
|
+
}
|
148
|
+
|
149
|
+
public interface SampleBufferTask
|
150
|
+
extends Task
|
151
|
+
{
|
152
|
+
@Config("sample_buffer_bytes")
|
153
|
+
@ConfigDefault("32768") // 32 * 1024
|
154
|
+
public int getSampleBufferBytes();
|
155
|
+
}
|
125
156
|
|
126
157
|
@Inject
|
127
158
|
public SamplingParserPlugin(@ForSystemConfig ConfigSource systemConfig)
|
128
159
|
{
|
129
|
-
this.
|
130
|
-
this.sampleSize = 32*1024; // TODO get sample size from system config. See also GuessExecutor.run.
|
131
|
-
Preconditions.checkArgument(minSampleSize < sampleSize, "minSampleSize must be smaller than sampleSize");
|
160
|
+
this.minSampleBufferBytes = 40; // empty gzip file is 33 bytes. // TODO get sample size from system config
|
132
161
|
}
|
133
162
|
|
134
163
|
@Override
|
135
164
|
public void transaction(ConfigSource config, ParserPlugin.Control control)
|
136
165
|
{
|
137
|
-
|
166
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
167
|
+
Preconditions.checkArgument(minSampleBufferBytes < task.getSampleBufferBytes(), "minSampleBufferBytes must be smaller than sample_buffer_bytes");
|
168
|
+
|
169
|
+
log.info("Try to read {} bytes from input source", numberFormat.format(task.getSampleBufferBytes()));
|
170
|
+
control.run(task.dump(), null);
|
138
171
|
}
|
139
172
|
|
140
173
|
@Override
|
141
174
|
public void run(TaskSource taskSource, Schema schema,
|
142
175
|
FileInput input, PageOutput output)
|
143
176
|
{
|
144
|
-
|
177
|
+
PluginTask task = taskSource.loadTask(PluginTask.class);
|
178
|
+
Buffer buffer = readSample(input, task.getSampleBufferBytes());
|
145
179
|
if (!taskSource.get(boolean.class, "force", false)) {
|
146
|
-
if (buffer.limit() <
|
180
|
+
if (buffer.limit() < minSampleBufferBytes) {
|
147
181
|
throw new NotEnoughSampleError(buffer.limit());
|
148
182
|
}
|
149
183
|
}
|
150
184
|
throw new SampledNoticeError(buffer);
|
151
185
|
}
|
152
186
|
|
153
|
-
public static Buffer readSample(FileInput fileInput, int
|
187
|
+
public static Buffer readSample(FileInput fileInput, int sampleBufferBytes)
|
154
188
|
{
|
155
|
-
return readSample(fileInput, Buffer.allocate(
|
189
|
+
return readSample(fileInput, Buffer.allocate(sampleBufferBytes), 0, sampleBufferBytes);
|
156
190
|
}
|
157
191
|
|
158
|
-
public static Buffer readSample(FileInput fileInput, Buffer sample, int offset, int
|
192
|
+
public static Buffer readSample(FileInput fileInput, Buffer sample, int offset, int sampleBufferBytes)
|
159
193
|
{
|
160
194
|
if (!fileInput.nextFile()) {
|
161
195
|
// no input files
|
@@ -168,7 +202,7 @@ public class SamplingParserPlugin
|
|
168
202
|
sample.setBytes(offset, buffer, 0, size);
|
169
203
|
offset += size;
|
170
204
|
buffer.release();
|
171
|
-
if (offset >=
|
205
|
+
if (offset >= sampleBufferBytes) {
|
172
206
|
break;
|
173
207
|
}
|
174
208
|
}
|
@@ -17,6 +17,8 @@ import org.embulk.exec.SamplingParserPlugin;
|
|
17
17
|
import org.embulk.exec.ConfigurableGuessInputPlugin;
|
18
18
|
import org.embulk.exec.NoSampleException;
|
19
19
|
|
20
|
+
import static org.embulk.exec.GuessExecutor.createSampleBufferConfigFromExecConfig;
|
21
|
+
|
20
22
|
public class FileInputRunner
|
21
23
|
implements InputPlugin, ConfigurableGuessInputPlugin
|
22
24
|
{
|
@@ -80,14 +82,15 @@ public class FileInputRunner
|
|
80
82
|
return guess(Exec.newConfigSource(), config);
|
81
83
|
}
|
82
84
|
|
83
|
-
public ConfigDiff guess(ConfigSource execConfig, ConfigSource
|
85
|
+
public ConfigDiff guess(ConfigSource execConfig, ConfigSource inputConfig)
|
84
86
|
{
|
85
|
-
|
87
|
+
final ConfigSource sampleBufferConfig = createSampleBufferConfigFromExecConfig(execConfig);
|
88
|
+
final Buffer sample = SamplingParserPlugin.runFileInputSampling(this, inputConfig, sampleBufferConfig);
|
86
89
|
// SamplingParserPlugin.runFileInputSampling throws NoSampleException if there're
|
87
90
|
// no files or all files are smaller than minSampleSize (40 bytes).
|
88
91
|
|
89
92
|
GuessExecutor guessExecutor = Exec.getInjector().getInstance(GuessExecutor.class);
|
90
|
-
return guessExecutor.guessParserConfig(sample,
|
93
|
+
return guessExecutor.guessParserConfig(sample, inputConfig, execConfig);
|
91
94
|
}
|
92
95
|
|
93
96
|
private class RunnerControl
|
@@ -1,16 +1,12 @@
|
|
1
1
|
package org.embulk.spi;
|
2
2
|
|
3
|
-
import java.io.Serializable;
|
4
|
-
import java.util.Map;
|
5
3
|
import java.util.List;
|
6
4
|
import java.util.Arrays;
|
7
5
|
import java.util.ArrayList;
|
8
|
-
import java.util.Comparator;
|
9
|
-
import java.util.Collections;
|
10
|
-
import com.google.common.collect.BiMap;
|
11
|
-
import com.google.common.collect.HashBiMap;
|
12
6
|
import io.airlift.slice.Slice;
|
13
7
|
import io.airlift.slice.Slices;
|
8
|
+
import org.embulk.spi.type.Type;
|
9
|
+
import org.embulk.spi.type.Types;
|
14
10
|
import org.msgpack.value.Value;
|
15
11
|
import org.msgpack.value.ImmutableValue;
|
16
12
|
import org.embulk.spi.time.Timestamp;
|
@@ -30,7 +26,8 @@ public class PageBuilder
|
|
30
26
|
private int count;
|
31
27
|
private int position;
|
32
28
|
private final byte[] nullBitSet;
|
33
|
-
private final
|
29
|
+
private final Row row;
|
30
|
+
private List<String> stringReferences = new ArrayList<>();
|
34
31
|
private List<ImmutableValue> valueReferences = new ArrayList<>();
|
35
32
|
private int referenceSize;
|
36
33
|
private int nextVariableLengthDataOffset;
|
@@ -43,6 +40,7 @@ public class PageBuilder
|
|
43
40
|
this.columnOffsets = PageFormat.columnOffsets(schema);
|
44
41
|
this.nullBitSet = new byte[PageFormat.nullBitSetSize(schema)];
|
45
42
|
Arrays.fill(nullBitSet, (byte) -1);
|
43
|
+
this.row = Row.newRow(schema);
|
46
44
|
this.fixedRecordSize = PageFormat.recordHeaderSize(schema) + PageFormat.totalColumnSize(schema);
|
47
45
|
this.nextVariableLengthDataOffset = fixedRecordSize;
|
48
46
|
newBuffer();
|
@@ -54,7 +52,7 @@ public class PageBuilder
|
|
54
52
|
this.bufferSlice = Slices.wrappedBuffer(buffer.array(), buffer.offset(), buffer.capacity());
|
55
53
|
this.count = 0;
|
56
54
|
this.position = PageFormat.PAGE_HEADER_SIZE;
|
57
|
-
this.stringReferences
|
55
|
+
this.stringReferences = new ArrayList<>();
|
58
56
|
this.valueReferences = new ArrayList<>();
|
59
57
|
this.referenceSize = 0;
|
60
58
|
}
|
@@ -71,12 +69,8 @@ public class PageBuilder
|
|
71
69
|
|
72
70
|
public void setNull(int columnIndex)
|
73
71
|
{
|
74
|
-
|
75
|
-
}
|
72
|
+
row.setNull(columnIndex);
|
76
73
|
|
77
|
-
private void clearNull(int columnIndex)
|
78
|
-
{
|
79
|
-
nullBitSet[columnIndex >>> 3] &= ~(1 << (columnIndex & 7));
|
80
74
|
}
|
81
75
|
|
82
76
|
public void setBoolean(Column column, boolean value)
|
@@ -87,8 +81,7 @@ public class PageBuilder
|
|
87
81
|
|
88
82
|
public void setBoolean(int columnIndex, boolean value)
|
89
83
|
{
|
90
|
-
|
91
|
-
clearNull(columnIndex);
|
84
|
+
row.setBoolean(columnIndex, value);
|
92
85
|
}
|
93
86
|
|
94
87
|
public void setLong(Column column, long value)
|
@@ -99,8 +92,7 @@ public class PageBuilder
|
|
99
92
|
|
100
93
|
public void setLong(int columnIndex, long value)
|
101
94
|
{
|
102
|
-
|
103
|
-
clearNull(columnIndex);
|
95
|
+
row.setLong(columnIndex, value);
|
104
96
|
}
|
105
97
|
|
106
98
|
public void setDouble(Column column, double value)
|
@@ -111,8 +103,7 @@ public class PageBuilder
|
|
111
103
|
|
112
104
|
public void setDouble(int columnIndex, double value)
|
113
105
|
{
|
114
|
-
|
115
|
-
clearNull(columnIndex);
|
106
|
+
row.setDouble(columnIndex, value);
|
116
107
|
}
|
117
108
|
|
118
109
|
public void setString(Column column, String value)
|
@@ -125,19 +116,10 @@ public class PageBuilder
|
|
125
116
|
{
|
126
117
|
if (value == null) {
|
127
118
|
setNull(columnIndex);
|
128
|
-
return;
|
129
119
|
}
|
130
|
-
|
131
|
-
|
132
|
-
if (reuseIndex != null) {
|
133
|
-
bufferSlice.setInt(getOffset(columnIndex), reuseIndex);
|
134
|
-
} else {
|
135
|
-
int index = stringReferences.size();
|
136
|
-
stringReferences.put(value, index);
|
137
|
-
bufferSlice.setInt(getOffset(columnIndex), index);
|
138
|
-
referenceSize += value.length() * 2 + 4; // assuming size of char = size of byte * 2 + length
|
120
|
+
else {
|
121
|
+
row.setString(columnIndex, value);
|
139
122
|
}
|
140
|
-
clearNull(columnIndex);
|
141
123
|
}
|
142
124
|
|
143
125
|
public void setJson(Column column, Value value)
|
@@ -150,14 +132,10 @@ public class PageBuilder
|
|
150
132
|
{
|
151
133
|
if (value == null) {
|
152
134
|
setNull(columnIndex);
|
153
|
-
return;
|
154
135
|
}
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
bufferSlice.setInt(getOffset(columnIndex), index);
|
159
|
-
referenceSize += 256; // TODO how to estimate size of the value?
|
160
|
-
clearNull(columnIndex);
|
136
|
+
else {
|
137
|
+
row.setJson(columnIndex, value);
|
138
|
+
}
|
161
139
|
}
|
162
140
|
|
163
141
|
public void setTimestamp(Column column, Timestamp value)
|
@@ -170,49 +148,76 @@ public class PageBuilder
|
|
170
148
|
{
|
171
149
|
if (value == null) {
|
172
150
|
setNull(columnIndex);
|
173
|
-
return;
|
174
151
|
}
|
152
|
+
else {
|
153
|
+
row.setTimestamp(columnIndex, value);
|
154
|
+
}
|
155
|
+
}
|
175
156
|
|
176
|
-
|
177
|
-
|
178
|
-
|
157
|
+
private void writeNull(int columnIndex)
|
158
|
+
{
|
159
|
+
nullBitSet[columnIndex >>> 3] |= (1 << (columnIndex & 7));
|
160
|
+
}
|
161
|
+
|
162
|
+
private void clearNull(int columnIndex)
|
163
|
+
{
|
164
|
+
nullBitSet[columnIndex >>> 3] &= ~(1 << (columnIndex & 7));
|
165
|
+
}
|
166
|
+
|
167
|
+
private void writeBoolean(int columnIndex, boolean value)
|
168
|
+
{
|
169
|
+
bufferSlice.setByte(getOffset(columnIndex), value ? (byte) 1 : (byte) 0);
|
179
170
|
clearNull(columnIndex);
|
180
171
|
}
|
181
172
|
|
182
|
-
private
|
173
|
+
private void writeLong(int columnIndex, long value)
|
183
174
|
{
|
184
|
-
|
175
|
+
bufferSlice.setLong(getOffset(columnIndex), value);
|
176
|
+
clearNull(columnIndex);
|
185
177
|
}
|
186
178
|
|
187
|
-
private
|
188
|
-
implements Comparator<Map.Entry<String, Integer>>, Serializable
|
179
|
+
private void writeDouble(int columnIndex, double value)
|
189
180
|
{
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
return e1.getValue().compareTo(e2.getValue());
|
194
|
-
}
|
181
|
+
bufferSlice.setDouble(getOffset(columnIndex), value);
|
182
|
+
clearNull(columnIndex);
|
183
|
+
}
|
195
184
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
185
|
+
private void writeString(int columnIndex, String value)
|
186
|
+
{
|
187
|
+
int index = stringReferences.size();
|
188
|
+
stringReferences.add(value);
|
189
|
+
bufferSlice.setInt(getOffset(columnIndex), index);
|
190
|
+
referenceSize += value.length() * 2 + 4; // assuming size of char = size of byte * 2 + length
|
191
|
+
clearNull(columnIndex);
|
201
192
|
}
|
202
193
|
|
203
|
-
private
|
194
|
+
private void writeJson(int columnIndex, Value value)
|
204
195
|
{
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
196
|
+
int index = valueReferences.size();
|
197
|
+
valueReferences.add(value.immutableValue());
|
198
|
+
bufferSlice.setInt(getOffset(columnIndex), index);
|
199
|
+
referenceSize += 256; // TODO how to estimate size of the value?
|
200
|
+
clearNull(columnIndex);
|
201
|
+
}
|
202
|
+
|
203
|
+
private void writeTimestamp(int columnIndex, Timestamp value)
|
204
|
+
{
|
205
|
+
int offset = getOffset(columnIndex);
|
206
|
+
bufferSlice.setLong(offset, value.getEpochSecond());
|
207
|
+
bufferSlice.setInt(offset + 8, value.getNano());
|
208
|
+
clearNull(columnIndex);
|
209
|
+
}
|
210
|
+
|
211
|
+
private int getOffset(int columnIndex)
|
212
|
+
{
|
213
|
+
return position + columnOffsets[columnIndex];
|
212
214
|
}
|
213
215
|
|
214
216
|
public void addRecord()
|
215
217
|
{
|
218
|
+
// record
|
219
|
+
row.write(this);
|
220
|
+
|
216
221
|
// record header
|
217
222
|
bufferSlice.setInt(position, nextVariableLengthDataOffset); // nextVariableLengthDataOffset means record size
|
218
223
|
bufferSlice.setBytes(position + 4, nullBitSet);
|
@@ -237,7 +242,7 @@ public class PageBuilder
|
|
237
242
|
|
238
243
|
// flush page
|
239
244
|
Page page = Page.wrap(buffer)
|
240
|
-
.setStringReferences(
|
245
|
+
.setStringReferences(stringReferences)
|
241
246
|
.setValueReferences(valueReferences);
|
242
247
|
buffer = null;
|
243
248
|
bufferSlice = null;
|
@@ -270,6 +275,322 @@ public class PageBuilder
|
|
270
275
|
output.close();
|
271
276
|
}
|
272
277
|
|
278
|
+
/**
|
279
|
+
* Row is a container to stage values before adding into reference lists such as |stringReferences|.
|
280
|
+
*
|
281
|
+
* |Row| works as a buffer against plugins that may add values incorrectly without |PageBuilder#addRecord|.
|
282
|
+
* It accepts just one value per column while |PageBuilder| can double-store values regardless of columns.
|
283
|
+
* Double-stored values are overwritten.
|
284
|
+
*/
|
285
|
+
private static class Row
|
286
|
+
{
|
287
|
+
private static Row newRow(Schema schema)
|
288
|
+
{
|
289
|
+
ColumnValue[] values = new ColumnValue[schema.getColumnCount()];
|
290
|
+
for (Column column : schema.getColumns()) {
|
291
|
+
values[column.getIndex()] = newValue(column);
|
292
|
+
}
|
293
|
+
return new Row(values);
|
294
|
+
}
|
295
|
+
|
296
|
+
private static ColumnValue newValue(Column column)
|
297
|
+
{
|
298
|
+
Type type = column.getType();
|
299
|
+
if (type.equals(Types.BOOLEAN)) {
|
300
|
+
return new BooleanColumnValue(column);
|
301
|
+
}
|
302
|
+
else if (type.equals(Types.DOUBLE)) {
|
303
|
+
return new DoubleColumnValue(column);
|
304
|
+
}
|
305
|
+
else if (type.equals(Types.LONG)) {
|
306
|
+
return new LongColumnValue(column);
|
307
|
+
}
|
308
|
+
else if (type.equals(Types.STRING)) {
|
309
|
+
return new StringColumnValue(column);
|
310
|
+
}
|
311
|
+
else if (type.equals(Types.JSON)) {
|
312
|
+
return new JsonColumnValue(column);
|
313
|
+
}
|
314
|
+
else if (type.equals(Types.TIMESTAMP)) {
|
315
|
+
return new TimestampColumnValue(column);
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
throw new IllegalStateException("Unsupported type " + type.getName());
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
private final ColumnValue[] values;
|
323
|
+
|
324
|
+
private Row(ColumnValue[] values)
|
325
|
+
{
|
326
|
+
this.values = values;
|
327
|
+
}
|
328
|
+
|
329
|
+
private void setNull(int columnIndex)
|
330
|
+
{
|
331
|
+
values[columnIndex].setNull();
|
332
|
+
}
|
333
|
+
|
334
|
+
private void setBoolean(int columnIndex, boolean value)
|
335
|
+
{
|
336
|
+
values[columnIndex].setBoolean(value);
|
337
|
+
}
|
338
|
+
|
339
|
+
private void setLong(int columnIndex, long value)
|
340
|
+
{
|
341
|
+
values[columnIndex].setLong(value);
|
342
|
+
}
|
343
|
+
|
344
|
+
private void setDouble(int columnIndex, double value)
|
345
|
+
{
|
346
|
+
values[columnIndex].setDouble(value);
|
347
|
+
}
|
348
|
+
|
349
|
+
private void setString(int columnIndex, String value)
|
350
|
+
{
|
351
|
+
values[columnIndex].setString(value);
|
352
|
+
}
|
353
|
+
|
354
|
+
private void setJson(int columnIndex, Value value)
|
355
|
+
{
|
356
|
+
values[columnIndex].setJson(value);
|
357
|
+
}
|
358
|
+
|
359
|
+
private void setTimestamp(int columnIndex, Timestamp value)
|
360
|
+
{
|
361
|
+
values[columnIndex].setTimestamp(value);
|
362
|
+
}
|
363
|
+
|
364
|
+
private void write(PageBuilder pageBuilder)
|
365
|
+
{
|
366
|
+
for (ColumnValue v : values) {
|
367
|
+
v.write(pageBuilder);
|
368
|
+
}
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
private interface ColumnValue
|
373
|
+
{
|
374
|
+
void setBoolean(boolean value);
|
375
|
+
|
376
|
+
void setLong(long value);
|
377
|
+
|
378
|
+
void setDouble(double value);
|
379
|
+
|
380
|
+
void setString(String value);
|
381
|
+
|
382
|
+
void setJson(Value value);
|
383
|
+
|
384
|
+
void setTimestamp(Timestamp value);
|
385
|
+
|
386
|
+
void setNull();
|
387
|
+
|
388
|
+
void write(PageBuilder pageBuilder);
|
389
|
+
}
|
390
|
+
|
391
|
+
private static abstract class AbstractColumnValue
|
392
|
+
implements ColumnValue
|
393
|
+
{
|
394
|
+
protected final Column column;
|
395
|
+
protected boolean isNull;
|
396
|
+
|
397
|
+
protected AbstractColumnValue(Column column)
|
398
|
+
{
|
399
|
+
this.column = column;
|
400
|
+
}
|
401
|
+
|
402
|
+
public void setBoolean(boolean value)
|
403
|
+
{
|
404
|
+
throw new IllegalStateException("Not reach here");
|
405
|
+
}
|
406
|
+
|
407
|
+
public void setLong(long value)
|
408
|
+
{
|
409
|
+
throw new IllegalStateException("Not reach here");
|
410
|
+
}
|
411
|
+
|
412
|
+
public void setDouble(double value)
|
413
|
+
{
|
414
|
+
throw new IllegalStateException("Not reach here");
|
415
|
+
}
|
416
|
+
|
417
|
+
public void setString(String value)
|
418
|
+
{
|
419
|
+
throw new IllegalStateException("Not reach here");
|
420
|
+
}
|
421
|
+
|
422
|
+
public void setJson(Value value)
|
423
|
+
{
|
424
|
+
throw new IllegalStateException("Not reach here");
|
425
|
+
}
|
426
|
+
|
427
|
+
public void setTimestamp(Timestamp value)
|
428
|
+
{
|
429
|
+
throw new IllegalStateException("Not reach here");
|
430
|
+
}
|
431
|
+
|
432
|
+
public void setNull()
|
433
|
+
{
|
434
|
+
isNull = true;
|
435
|
+
}
|
436
|
+
|
437
|
+
public void write(PageBuilder pageBuilder)
|
438
|
+
{
|
439
|
+
if (!isNull) {
|
440
|
+
writeNotNull(pageBuilder);
|
441
|
+
}
|
442
|
+
else {
|
443
|
+
pageBuilder.writeNull(column.getIndex());
|
444
|
+
}
|
445
|
+
}
|
446
|
+
|
447
|
+
protected abstract void writeNotNull(PageBuilder pageBuilder);
|
448
|
+
}
|
449
|
+
|
450
|
+
private static class BooleanColumnValue
|
451
|
+
extends AbstractColumnValue
|
452
|
+
{
|
453
|
+
private boolean value;
|
454
|
+
|
455
|
+
BooleanColumnValue(Column column)
|
456
|
+
{
|
457
|
+
super(column);
|
458
|
+
}
|
459
|
+
|
460
|
+
@Override
|
461
|
+
public void setBoolean(boolean value)
|
462
|
+
{
|
463
|
+
this.value = value;
|
464
|
+
this.isNull = false;
|
465
|
+
}
|
466
|
+
|
467
|
+
@Override
|
468
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
469
|
+
{
|
470
|
+
pageBuilder.writeBoolean(column.getIndex(), value);
|
471
|
+
}
|
472
|
+
}
|
473
|
+
|
474
|
+
private static class LongColumnValue
|
475
|
+
extends AbstractColumnValue
|
476
|
+
{
|
477
|
+
private long value;
|
478
|
+
|
479
|
+
LongColumnValue(Column column)
|
480
|
+
{
|
481
|
+
super(column);
|
482
|
+
}
|
483
|
+
|
484
|
+
@Override
|
485
|
+
public void setLong(long value)
|
486
|
+
{
|
487
|
+
this.value = value;
|
488
|
+
this.isNull = false;
|
489
|
+
}
|
490
|
+
|
491
|
+
@Override
|
492
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
493
|
+
{
|
494
|
+
pageBuilder.writeLong(column.getIndex(), value);
|
495
|
+
}
|
496
|
+
}
|
497
|
+
|
498
|
+
private static class DoubleColumnValue
|
499
|
+
extends AbstractColumnValue
|
500
|
+
{
|
501
|
+
private double value;
|
502
|
+
|
503
|
+
DoubleColumnValue(Column column)
|
504
|
+
{
|
505
|
+
super(column);
|
506
|
+
}
|
507
|
+
|
508
|
+
@Override
|
509
|
+
public void setDouble(double value)
|
510
|
+
{
|
511
|
+
this.value = value;
|
512
|
+
this.isNull = false;
|
513
|
+
}
|
514
|
+
|
515
|
+
@Override
|
516
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
517
|
+
{
|
518
|
+
pageBuilder.writeDouble(column.getIndex(), value);
|
519
|
+
}
|
520
|
+
}
|
521
|
+
|
522
|
+
private static class StringColumnValue
|
523
|
+
extends AbstractColumnValue
|
524
|
+
{
|
525
|
+
private String value;
|
526
|
+
|
527
|
+
StringColumnValue(Column column)
|
528
|
+
{
|
529
|
+
super(column);
|
530
|
+
}
|
531
|
+
|
532
|
+
@Override
|
533
|
+
public void setString(String value)
|
534
|
+
{
|
535
|
+
this.value = value;
|
536
|
+
this.isNull = false;
|
537
|
+
}
|
538
|
+
|
539
|
+
@Override
|
540
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
541
|
+
{
|
542
|
+
pageBuilder.writeString(column.getIndex(), value);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
546
|
+
private static class JsonColumnValue
|
547
|
+
extends AbstractColumnValue
|
548
|
+
{
|
549
|
+
private Value value;
|
550
|
+
|
551
|
+
JsonColumnValue(Column column)
|
552
|
+
{
|
553
|
+
super(column);
|
554
|
+
}
|
555
|
+
|
556
|
+
@Override
|
557
|
+
public void setJson(Value value)
|
558
|
+
{
|
559
|
+
this.value = value;
|
560
|
+
this.isNull = false;
|
561
|
+
}
|
562
|
+
|
563
|
+
@Override
|
564
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
565
|
+
{
|
566
|
+
pageBuilder.writeJson(column.getIndex(), value);
|
567
|
+
}
|
568
|
+
}
|
569
|
+
|
570
|
+
private static class TimestampColumnValue
|
571
|
+
extends AbstractColumnValue
|
572
|
+
{
|
573
|
+
private Timestamp value;
|
574
|
+
|
575
|
+
TimestampColumnValue(Column column)
|
576
|
+
{
|
577
|
+
super(column);
|
578
|
+
}
|
579
|
+
|
580
|
+
@Override
|
581
|
+
public void setTimestamp(Timestamp value)
|
582
|
+
{
|
583
|
+
this.value = value;
|
584
|
+
this.isNull = false;
|
585
|
+
}
|
586
|
+
|
587
|
+
@Override
|
588
|
+
public void writeNotNull(PageBuilder pageBuilder)
|
589
|
+
{
|
590
|
+
pageBuilder.writeTimestamp(column.getIndex(), value);
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
273
594
|
/* TODO for variable-length types
|
274
595
|
private void flushAndTakeOverRemaingData()
|
275
596
|
{
|