td 0.10.99 → 0.11.1
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 +15 -0
- data/.gitignore +3 -0
- data/ChangeLog +30 -1
- data/Rakefile +1 -1
- data/bin/td +21 -4
- data/contrib/completion/{td-comletion.bash → td-completion.bash} +0 -0
- data/dist/resources/exe/td +1 -1
- data/dist/resources/pkg/td +2 -2
- data/java/logging.properties +1 -0
- data/lib/td/command/common.rb +47 -18
- data/lib/td/command/export.rb +2 -2
- data/lib/td/command/import.rb +20 -71
- data/lib/td/command/job.rb +109 -16
- data/lib/td/command/list.rb +9 -7
- data/lib/td/command/query.rb +35 -27
- data/lib/td/command/result.rb +18 -2
- data/lib/td/command/runner.rb +18 -10
- data/lib/td/command/sched.rb +15 -3
- data/lib/td/command/schema.rb +5 -1
- data/lib/td/command/status.rb +1 -1
- data/lib/td/command/table.rb +26 -11
- data/lib/td/command/update.rb +9 -10
- data/lib/td/updater.rb +231 -29
- data/lib/td/version.rb +1 -3
- data/spec/td/updater_spec.rb +29 -0
- data/spec/td/version_spec.rb +1 -1
- data/td.gemspec +2 -2
- metadata +10 -40
- data/build/update-td-import-java.sh +0 -44
- data/java/VERSION +0 -1
- data/java/td-import-java.version +0 -1
- data/java/td-import.jar +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MjhhYWI5NWE1ZmI3ZTkwZjY0OTNhMGE3N2VjNjUzNzk2ZWY2OGJkYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDZmMDJlMDQyZmViMjY5NTNmMTE0ODg5ZWE2MGYxZjJhYTg4Y2VhZQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NGZmMTk4ZTk5ZWFhYzc4YmEyZTE0ZmI0MjA2ODYzOWQxNzQ0ZTc5OGRjZDhh
|
10
|
+
OTI0NjJiZjA3MDhiZmFjNjg3MThjNjI1ZjcyZjNiOTNiOWU5MjQ2M2FhOWRh
|
11
|
+
ZTI4OGI2ZTk1YTEwYmVkZGJmNGU4Y2YzYTY1ZDc5MmNkYTI5ZTQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NjNiNTI4MGI4MDY0MGYzMjZiMTBmNzBhYzJmNjNmZjcxZDgxZWVjNTgzYzUx
|
14
|
+
ZGZiMzViYmQ0ZjQwNWIwZmI5MWQ5ZmExYTA3MzZkZDlkY2RmNTEzNDMxYzNj
|
15
|
+
ZGJhZTFlZDExYjc4YzdkYzUwZmJjNjc3NTlkZGQ5OTI2MDQ4NjY=
|
data/.gitignore
CHANGED
data/ChangeLog
CHANGED
@@ -1,10 +1,39 @@
|
|
1
|
+
== 2014-04-29 version 0.11.1
|
2
|
+
|
3
|
+
* Fix Treasure Data query result output database and table validation
|
4
|
+
regular expression
|
5
|
+
* Fixed auto updater which threw a warning due to a constant being
|
6
|
+
reinitialized
|
7
|
+
* Interpret the CPU time as number of milliseconds as opposed to
|
8
|
+
number of seconds in the job:show output
|
9
|
+
* when outputting the query result to file, flush the data every
|
10
|
+
100 records
|
11
|
+
|
12
|
+
== 2014-04-23 version 0.11.0
|
13
|
+
|
14
|
+
* Show cumulative CPU time in the job:list and job:show outputs
|
15
|
+
* The error message when the specified schema has columns containing upper case
|
16
|
+
alphanumeric characters is improved to be more representative of the problem
|
17
|
+
* 'td query' commands with result output to Treasure Data (--result td://xxxx)
|
18
|
+
validate the database and table naming convention before running the query
|
19
|
+
* The Java bulk import JAR file is now auto-updated. Checking for an updated
|
20
|
+
version is performed hourly
|
21
|
+
* 'td query' commands with result output specification invite the user to use
|
22
|
+
the '-x / --exclude' option to avoid outputting the query result to stdout as
|
23
|
+
well
|
24
|
+
* The 'Destination' field in the summary for the Bulk import perform output
|
25
|
+
from the jobs:show command contains the destination table name in the form of
|
26
|
+
a LOAD DATA SESSION query
|
27
|
+
* Returning the correct non-zero error codes in the occurrence of an exception
|
28
|
+
* Declare the 'td query' option '--sampling' obsolete. A warning indicating the
|
29
|
+
option is obsolete and has no effect will be printed to warn the user
|
30
|
+
|
1
31
|
== 2014-02-26 version 0.10.99
|
2
32
|
|
3
33
|
* job:show, query: limit the number of records ouputted when printing on stdout using the -l / --limit option
|
4
34
|
* job:show, query: optionally output/store csv and tsv files with headers using the -c / --column-names option
|
5
35
|
* job:show, query: support result output from Presto
|
6
36
|
|
7
|
-
|
8
37
|
== 2014-02-21 version 0.10.98
|
9
38
|
|
10
39
|
* import:unfreeze: fixed NoMethodError error
|
data/Rakefile
CHANGED
data/bin/td
CHANGED
@@ -1,17 +1,34 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- coding: utf-8 -*-
|
3
|
+
|
3
4
|
require 'rubygems' unless defined?(gem)
|
4
5
|
gem 'td-client'
|
5
6
|
here = File.dirname(__FILE__)
|
6
7
|
$LOAD_PATH << File.expand_path(File.join(here, '..', 'lib'))
|
7
8
|
|
9
|
+
# disable the updater for the td gem
|
8
10
|
require 'td/updater'
|
9
11
|
TreasureData::Updater.disable(<<EOS
|
10
|
-
|
11
|
-
|
12
|
+
|
13
|
+
`td update` is only available from the Treasure Data Toolbelt.
|
14
|
+
You can download and install it from http://toolbelt.treasure-data.com.
|
15
|
+
|
16
|
+
It appers you are running the `td` gem. To update the gem to the latest
|
17
|
+
version, please run `gem update td`.
|
18
|
+
|
19
|
+
Please note that if you install `td` with `bundler` in a Gemfile/Gemspec
|
20
|
+
federated environment, you will need to upgrade the reference version for
|
21
|
+
`td` in the Gemfile/Gemspec for the updated `td` version to be used after
|
22
|
+
updating it.
|
23
|
+
|
12
24
|
EOS
|
13
25
|
)
|
14
26
|
|
27
|
+
# start up the CLI
|
15
28
|
require 'td/command/runner'
|
16
|
-
TreasureData::Command::Runner.new.run ARGV
|
17
|
-
|
29
|
+
ev = TreasureData::Command::Runner.new.run ARGV
|
30
|
+
unless ev.nil?
|
31
|
+
exit ev
|
32
|
+
else
|
33
|
+
puts "No exit status"
|
34
|
+
end
|
File without changes
|
data/dist/resources/exe/td
CHANGED
data/dist/resources/pkg/td
CHANGED
data/java/logging.properties
CHANGED
@@ -35,6 +35,7 @@ handlers= java.util.logging.FileHandler
|
|
35
35
|
|
36
36
|
java.util.logging.FileHandler.level = INFO
|
37
37
|
java.util.logging.FileHandler.pattern=td-bulk-import.log
|
38
|
+
java.util.logging.FileHandler.append=true
|
38
39
|
java.util.logging.FileHandler.limit = 50000
|
39
40
|
java.util.logging.FileHandler.count = 1
|
40
41
|
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
|
data/lib/td/command/common.rb
CHANGED
@@ -11,6 +11,12 @@ autoload :Job, 'td/client'
|
|
11
11
|
|
12
12
|
module Command
|
13
13
|
|
14
|
+
class ParameterConfigurationError < ArgumentError
|
15
|
+
end
|
16
|
+
|
17
|
+
class BulkImportExecutionError < ArgumentError
|
18
|
+
end
|
19
|
+
|
14
20
|
private
|
15
21
|
def initialize
|
16
22
|
@render_indent = ''
|
@@ -24,7 +30,7 @@ module Command
|
|
24
30
|
unless apikey
|
25
31
|
raise ConfigError, "Account is not configured."
|
26
32
|
end
|
27
|
-
opts[:user_agent] = "TD: #{
|
33
|
+
opts[:user_agent] = "TD: #{TOOLBELT_VERSION}"
|
28
34
|
if h = ENV['TD_API_HEADERS']
|
29
35
|
pairs = h.split("\n")
|
30
36
|
opts[:headers] = Hash[pairs.map {|pair| pair.split('=', 2) }]
|
@@ -105,30 +111,53 @@ EOS
|
|
105
111
|
end
|
106
112
|
end
|
107
113
|
|
108
|
-
def
|
114
|
+
def humanize_time(time, is_ms = false)
|
115
|
+
if time.nil?
|
116
|
+
return ''
|
117
|
+
end
|
118
|
+
|
119
|
+
time = time.to_i
|
120
|
+
millisecs = nil
|
121
|
+
elapsed = ''
|
122
|
+
|
123
|
+
if is_ms
|
124
|
+
# store the first 3 decimals
|
125
|
+
millisecs = time % 1000
|
126
|
+
time /= 1000
|
127
|
+
end
|
128
|
+
|
129
|
+
if time >= 3600
|
130
|
+
elapsed << "#{time / 3600}h "
|
131
|
+
time %= 3600
|
132
|
+
elapsed << "%dm " % (time / 60)
|
133
|
+
time %= 60
|
134
|
+
elapsed << "%ds" % time
|
135
|
+
elsif time >= 60
|
136
|
+
elapsed << "%dm " % (time / 60)
|
137
|
+
time %= 60
|
138
|
+
elapsed << "%ds" % time
|
139
|
+
elsif time > 0
|
140
|
+
elapsed << "%ds" % time
|
141
|
+
end
|
142
|
+
|
143
|
+
if is_ms and millisecs > 0
|
144
|
+
elapsed << " %03dms" % millisecs
|
145
|
+
end
|
146
|
+
|
147
|
+
elapsed
|
148
|
+
end
|
149
|
+
|
150
|
+
# assumed to
|
151
|
+
def humanize_elapsed_time(start, finish)
|
109
152
|
if start
|
110
153
|
if !finish
|
111
154
|
finish = Time.now.utc
|
112
155
|
end
|
113
|
-
|
114
|
-
elapsed = ''
|
115
|
-
if e >= 3600
|
116
|
-
elapsed << "#{e/3600}h "
|
117
|
-
e %= 3600
|
118
|
-
elapsed << "%2dm " % (e/60)
|
119
|
-
e %= 60
|
120
|
-
elapsed << "%2dsec" % e
|
121
|
-
elsif e >= 60
|
122
|
-
elapsed << "%2dm " % (e/60)
|
123
|
-
e %= 60
|
124
|
-
elapsed << "%2dsec" % e
|
125
|
-
else
|
126
|
-
elapsed << "%2dsec" % e
|
127
|
-
end
|
156
|
+
elapsed = humanize_time(finish.to_i - start.to_i, false)
|
128
157
|
else
|
129
158
|
elapsed = ''
|
130
159
|
end
|
131
|
-
elapsed
|
160
|
+
elapsed
|
132
161
|
end
|
133
162
|
|
134
163
|
def get_database(client, db_name)
|
data/lib/td/command/export.rb
CHANGED
@@ -9,7 +9,7 @@ module Command
|
|
9
9
|
s3_bucket = nil
|
10
10
|
aws_access_key_id = nil
|
11
11
|
aws_secret_access_key = nil
|
12
|
-
file_format =
|
12
|
+
file_format = "json.gz" # default
|
13
13
|
|
14
14
|
op.on('-f', '--from TIME', 'export data which is newer than or same with the TIME') {|s|
|
15
15
|
from = export_parse_time(s)
|
@@ -26,7 +26,7 @@ module Command
|
|
26
26
|
op.on('-s', '--aws-secret-key SECRET_KEY', 'AWS secret access key to export data (required)') {|s|
|
27
27
|
aws_secret_access_key = s
|
28
28
|
}
|
29
|
-
op.on('-F', '--file-format FILE_FORMAT', 'file format for exported data, either json.gz (default) or line-json.gz') { |s|
|
29
|
+
op.on('-F', '--file-format FILE_FORMAT', 'file format for exported data, either json.gz (default) or line-json.gz') { |s|
|
30
30
|
raise ArgumentError, "#{s} is not a supported file format" unless SUPPORTED_FORMATS.include?(s)
|
31
31
|
file_format = s
|
32
32
|
}
|
data/lib/td/command/import.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'td/updater'
|
2
|
+
require 'time'
|
2
3
|
|
3
4
|
module TreasureData
|
4
5
|
module Command
|
5
|
-
|
6
|
-
BASE_PATH = File.expand_path('../../..', File.dirname(__FILE__))
|
7
|
-
UPDATED_PATH = File.join(Updater.home_directory, ".td", "java")
|
6
|
+
include TreasureData::Updater
|
8
7
|
|
9
8
|
JAVA_COMMAND = "java"
|
10
9
|
JAVA_MAIN_CLASS = "com.treasure_data.td_import.BulkImportCommand"
|
@@ -25,37 +24,13 @@ module Command
|
|
25
24
|
bulk_import_create(op)
|
26
25
|
end
|
27
26
|
|
28
|
-
def
|
29
|
-
|
30
|
-
puts "td-import-java #{File.open(
|
27
|
+
def import_jar_version(op)
|
28
|
+
version = find_version_file
|
29
|
+
puts "td-import-java #{File.open(version, 'r').read}"
|
31
30
|
end
|
32
31
|
|
33
32
|
def import_jar_update(op)
|
34
|
-
|
35
|
-
|
36
|
-
require 'rexml/document'
|
37
|
-
require 'open-uri'
|
38
|
-
require 'fileutils'
|
39
|
-
|
40
|
-
doc = REXML::Document.new(open('http://maven.treasure-data.com/com/treasure_data/td-import/maven-metadata.xml') { |f| f.read })
|
41
|
-
updated = Time.strptime(REXML::XPath.match(doc, '/metadata/versioning/lastUpdated').first.text, "%Y%m%d%H%M%S")
|
42
|
-
version = REXML::XPath.match(doc, '/metadata/versioning/release').first.text
|
43
|
-
|
44
|
-
# Convert into UTF to compare time correctly
|
45
|
-
updated = (updated + updated.gmt_offset).utc unless updated.gmt?
|
46
|
-
last_updated = last_updated.utc unless last_updated.gmt?
|
47
|
-
|
48
|
-
if updated > last_updated
|
49
|
-
FileUtils.mkdir_p(UPDATED_PATH) unless File.exist?(UPDATED_PATH)
|
50
|
-
File.open(File.join(UPDATED_PATH, 'VERSION'), 'w') { |f| f.print "#{version} via import:jar_update" }
|
51
|
-
File.open(File.join(UPDATED_PATH, 'td-import-java.version'), 'w') { |f| f.print "#{version} #{updated}" }
|
52
|
-
File.open(File.join(UPDATED_PATH, 'td-import.jar'), 'wb') { |f|
|
53
|
-
f.print Updater.fetch("http://maven.treasure-data.com/com/treasure_data/td-import/#{version}/td-import-#{version}-jar-with-dependencies.jar")
|
54
|
-
}
|
55
|
-
puts "Installed td-import.jar #{version} into #{UPDATED_PATH}"
|
56
|
-
else
|
57
|
-
puts 'Installed td-import.jar is latest version'
|
58
|
-
end
|
33
|
+
check_n_update_jar(false)
|
59
34
|
end
|
60
35
|
|
61
36
|
def import_prepare(op)
|
@@ -100,8 +75,14 @@ module Command
|
|
100
75
|
bulk_import_unfreeze(op)
|
101
76
|
end
|
102
77
|
|
78
|
+
#
|
79
|
+
# Module private methods - don't map to import:* commands
|
80
|
+
#
|
81
|
+
|
103
82
|
private
|
104
83
|
def import_by_java(subcmd)
|
84
|
+
check_n_update_jar(true)
|
85
|
+
|
105
86
|
# check java runtime exists or not
|
106
87
|
check_java
|
107
88
|
|
@@ -122,6 +103,10 @@ module Command
|
|
122
103
|
|
123
104
|
cmd = [JAVA_COMMAND] + JVM_OPTS + java_args
|
124
105
|
system(*cmd)
|
106
|
+
if $?.exitstatus != 0
|
107
|
+
raise BulkImportExecutionError,
|
108
|
+
"Bulk Import returned error #{$?.exitstatus}. Please check the 'td-bulk-import.log' logfile for details."
|
109
|
+
end
|
125
110
|
end
|
126
111
|
|
127
112
|
private
|
@@ -136,20 +121,10 @@ module Command
|
|
136
121
|
|
137
122
|
unless $?.success?
|
138
123
|
$stderr.puts "Java is not installed. 'td import' command requires Java (version 1.6 or later)."
|
139
|
-
$stderr.puts "Alternatively, you can use 'bulk_import' commands
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
private
|
145
|
-
def find_td_import_jar
|
146
|
-
libjars = find_files('*.jar')
|
147
|
-
found = libjars.find { |path| File.basename(path) =~ /^td-import/ }
|
148
|
-
if found.nil?
|
149
|
-
$stderr.puts "td-import.jar is not found."
|
124
|
+
$stderr.puts "Alternatively, you can use the 'bulk_import' commands."
|
125
|
+
$stderr.puts "Since they are implemented in Ruby, they perform significantly slower."
|
150
126
|
exit 1
|
151
127
|
end
|
152
|
-
found
|
153
128
|
end
|
154
129
|
|
155
130
|
private
|
@@ -158,13 +133,12 @@ module Command
|
|
158
133
|
|
159
134
|
# set apiserver
|
160
135
|
set_sysprops_endpoint(sysprops)
|
161
|
-
|
162
136
|
# set http_proxy
|
163
137
|
set_sysprops_http_proxy(sysprops)
|
164
138
|
|
165
139
|
# set configuration file for logging
|
166
|
-
conf_file =
|
167
|
-
|
140
|
+
conf_file = find_logging_property
|
141
|
+
unless conf_file.empty?
|
168
142
|
sysprops << "-Djava.util.logging.config.file=#{conf_file}"
|
169
143
|
end
|
170
144
|
|
@@ -223,30 +197,5 @@ module Command
|
|
223
197
|
end
|
224
198
|
end
|
225
199
|
|
226
|
-
private
|
227
|
-
def try_find_logging_conf_file
|
228
|
-
libjars = Dir.glob("#{BASE_PATH}/java/**/*.properties")
|
229
|
-
libjars.find { |path| File.basename(path) =~ /^logging.properties/ }
|
230
|
-
end
|
231
|
-
|
232
|
-
private
|
233
|
-
def find_version_file
|
234
|
-
vfile = find_files('VERSION')
|
235
|
-
vfile
|
236
|
-
end
|
237
|
-
|
238
|
-
def existence_jar_updated_time
|
239
|
-
require 'time'
|
240
|
-
|
241
|
-
content = File.open(find_files("td-import-java.version").first).read
|
242
|
-
index = content.index(' ')
|
243
|
-
Time.parse(content[index + 1..-1].strip)
|
244
|
-
end
|
245
|
-
|
246
|
-
def find_files(target)
|
247
|
-
files = Dir.glob("#{UPDATED_PATH}/**/#{target}")
|
248
|
-
return files unless files.empty?
|
249
|
-
Dir.glob("#{BASE_PATH}/java/**/#{target}")
|
250
|
-
end
|
251
200
|
end
|
252
201
|
end
|
data/lib/td/command/job.rb
CHANGED
@@ -67,17 +67,33 @@ module Command
|
|
67
67
|
conditions = {:slower_than => slower_than}
|
68
68
|
end
|
69
69
|
|
70
|
-
jobs = client.jobs(skip, skip+max-1, status, conditions)
|
70
|
+
jobs = client.jobs(skip, skip + max - 1, status, conditions)
|
71
71
|
|
72
72
|
rows = []
|
73
73
|
jobs.each {|job|
|
74
74
|
start = job.start_at
|
75
|
-
elapsed =
|
75
|
+
elapsed = humanize_elapsed_time(start, job.end_at)
|
76
|
+
cpu_time = humanize_time(job.cpu_time, true)
|
76
77
|
priority = job_priority_name_of(job.priority)
|
77
|
-
rows << {
|
78
|
+
rows << {
|
79
|
+
:JobID => job.job_id,
|
80
|
+
:Database => job.db_name,
|
81
|
+
:Status => job.status,
|
82
|
+
:Type => job.type,
|
83
|
+
:Query => job.query.to_s[0,50] + " ...",
|
84
|
+
:Start => (start ? start.localtime : ''),
|
85
|
+
:Elapsed => elapsed.rjust(11),
|
86
|
+
:CPUTime => cpu_time.rjust(17),
|
87
|
+
:Priority => priority,
|
88
|
+
:Result => job.result_url
|
89
|
+
}
|
78
90
|
}
|
79
91
|
|
80
|
-
puts cmd_render_table(rows,
|
92
|
+
puts cmd_render_table(rows,
|
93
|
+
:fields => [:JobID, :Status, :Start, :Elapsed, :CPUTime, :Priority, :Result, :Type, :Database, :Query],
|
94
|
+
:max_width => 1000,
|
95
|
+
:render_format => op.render_format
|
96
|
+
)
|
81
97
|
end
|
82
98
|
|
83
99
|
def job_show(op)
|
@@ -102,9 +118,9 @@ module Command
|
|
102
118
|
output = s
|
103
119
|
format = 'tsv' if format.nil?
|
104
120
|
}
|
105
|
-
op.on('-f', '--format FORMAT', 'format of the result to write to the file (tsv, csv, json
|
121
|
+
op.on('-f', '--format FORMAT', 'format of the result to write to the file (tsv, csv, json, msgpack, and msgpack.gz)') {|s|
|
106
122
|
unless ['tsv', 'csv', 'json', 'msgpack', 'msgpack.gz'].include?(s)
|
107
|
-
raise "Unknown format #{s.dump}. Supported
|
123
|
+
raise "Unknown format #{s.dump}. Supported formats are: tsv, csv, json, msgpack, and msgpack.gz"
|
108
124
|
end
|
109
125
|
format = s
|
110
126
|
}
|
@@ -114,7 +130,8 @@ module Command
|
|
114
130
|
end
|
115
131
|
limit = s.to_i
|
116
132
|
}
|
117
|
-
op.on('-c', '--column-header', 'output of the columns\' header when the schema is available
|
133
|
+
op.on('-c', '--column-header', 'output of the columns\' header when the schema is available',
|
134
|
+
' for the table (only applies to tsv and csv formats)', TrueClass) {|b|
|
118
135
|
render_opts[:header] = b;
|
119
136
|
}
|
120
137
|
op.on('-x', '--exclude', 'do not automatically retrieve the job result', TrueClass) {|b|
|
@@ -127,19 +144,21 @@ module Command
|
|
127
144
|
|
128
145
|
if output.nil? && format
|
129
146
|
unless ['tsv', 'csv', 'json'].include?(format)
|
130
|
-
raise
|
147
|
+
raise ParameterConfigurationError,
|
148
|
+
"Supported formats are only tsv, csv and json without -o / --output option"
|
131
149
|
end
|
132
150
|
end
|
133
151
|
|
134
152
|
if render_opts[:header]
|
135
153
|
unless ['tsv', 'csv'].include?(format)
|
136
|
-
raise
|
154
|
+
raise ParameterConfigurationError,
|
155
|
+
"Option -c / --column-header is only supported with tsv and csv formats"
|
137
156
|
end
|
138
157
|
end
|
139
158
|
|
140
159
|
if !output.nil? && !limit.nil?
|
141
|
-
raise
|
142
|
-
"(no -o / --output option provided)"
|
160
|
+
raise ParameterConfigurationError,
|
161
|
+
"Option -l / --limit is only valid when not outputting to file (no -o / --output option provided)"
|
143
162
|
end
|
144
163
|
|
145
164
|
client = get_client
|
@@ -157,6 +176,12 @@ module Command
|
|
157
176
|
puts "Retry limit : #{job.retry_limit}"
|
158
177
|
puts "Output : #{job.result_url}"
|
159
178
|
puts "Query : #{job.query}"
|
179
|
+
elsif job.type == :bulk_import_perform
|
180
|
+
puts "Destination : #{job.query}"
|
181
|
+
end
|
182
|
+
# if the job is done and is of type hive, show the Map-Reduce cumulated CPU time
|
183
|
+
if job.finished? && [:hive].include?(job.type)
|
184
|
+
puts "CPU time : #{humanize_time(job.cpu_time, true)}"
|
160
185
|
end
|
161
186
|
|
162
187
|
if wait && !job.finished?
|
@@ -183,14 +208,14 @@ module Command
|
|
183
208
|
if verbose
|
184
209
|
if !job.debug['cmdout'].nil?
|
185
210
|
puts ""
|
186
|
-
puts "
|
211
|
+
puts "Output:"
|
187
212
|
job.debug['cmdout'].to_s.split("\n").each {|line|
|
188
213
|
puts " " + line
|
189
214
|
}
|
190
215
|
end
|
191
216
|
if !job.debug['stderr'].nil?
|
192
217
|
puts ""
|
193
|
-
puts "
|
218
|
+
puts "Details:"
|
194
219
|
job.debug['stderr'].to_s.split("\n").each {|line|
|
195
220
|
puts " " + line
|
196
221
|
}
|
@@ -198,7 +223,7 @@ module Command
|
|
198
223
|
end
|
199
224
|
end
|
200
225
|
|
201
|
-
|
226
|
+
puts "Use '-v' option to show detailed messages." unless verbose
|
202
227
|
end
|
203
228
|
|
204
229
|
def job_status(op)
|
@@ -262,12 +287,33 @@ module Command
|
|
262
287
|
write_result(job, output, limit, format, render_opts)
|
263
288
|
puts "written to #{output} in #{format} format"
|
264
289
|
else
|
290
|
+
# every format that is allowed on stdout
|
265
291
|
render_result(job, limit, format, render_opts)
|
266
292
|
end
|
267
293
|
end
|
268
294
|
|
269
295
|
def write_result(job, output, limit, format, render_opts={})
|
270
296
|
|
297
|
+
# start progress indicator
|
298
|
+
line_len = 0
|
299
|
+
start_time = last_time = Time.now.to_i
|
300
|
+
base_msg = "WARNING: the query result is being written"
|
301
|
+
if !output.nil?
|
302
|
+
msg = base_msg + "\r"
|
303
|
+
line_len += msg.length
|
304
|
+
print msg
|
305
|
+
end
|
306
|
+
|
307
|
+
# this lambda is passed on as a block when outputing the results to file
|
308
|
+
progress = lambda {
|
309
|
+
if (time = Time.now.to_i) - last_time > 5
|
310
|
+
msg = base_msg + ": #{humanize_time(time - start_time)} elapsed" + " " * 10 + "\r"
|
311
|
+
line_len = msg.length
|
312
|
+
print msg
|
313
|
+
last_time = time
|
314
|
+
end
|
315
|
+
}
|
316
|
+
|
271
317
|
# the next 3 formats allow writing to both a file and stdout
|
272
318
|
|
273
319
|
case format
|
@@ -281,6 +327,9 @@ module Command
|
|
281
327
|
f.write Yajl.dump(row)
|
282
328
|
n_rows += 1
|
283
329
|
break if output.nil? and !limit.nil? and n_rows == limit
|
330
|
+
|
331
|
+
# update progress indicator
|
332
|
+
progress.call if !output.nil?
|
284
333
|
}
|
285
334
|
f.write "]"
|
286
335
|
}
|
@@ -306,12 +355,17 @@ module Command
|
|
306
355
|
dump_column(col)
|
307
356
|
}
|
308
357
|
n_rows += 1
|
358
|
+
writer.flush if n_rows % 100 == 0 # flush every 100 recods
|
309
359
|
break if output.nil? and !limit.nil? and n_rows == limit
|
360
|
+
|
361
|
+
# update progress indicator
|
362
|
+
progress.call if !output.nil?
|
310
363
|
}
|
311
364
|
}
|
312
365
|
|
313
366
|
when 'tsv'
|
314
367
|
require 'yajl'
|
368
|
+
|
315
369
|
open_file(output, "w") {|f|
|
316
370
|
# output headers
|
317
371
|
if render_opts[:header] && job.hive_result_schema
|
@@ -332,25 +386,43 @@ module Command
|
|
332
386
|
}
|
333
387
|
f.write "\n"
|
334
388
|
n_rows += 1
|
389
|
+
f.flush if n_rows % 100 == 0 # flush every 100 recods
|
335
390
|
break if output.nil? and !limit.nil? and n_rows == limit
|
391
|
+
|
392
|
+
# update progress indicator
|
393
|
+
progress.call if !output.nil?
|
336
394
|
}
|
337
395
|
}
|
338
396
|
|
339
397
|
# these last 2 formats are only valid if writing the result to file through the -o/--output option.
|
340
398
|
|
341
399
|
when 'msgpack'
|
400
|
+
if output.nil?
|
401
|
+
raise ParameterConfigurationError,
|
402
|
+
"Format 'msgpack' does not support writing to stdout"
|
403
|
+
end
|
342
404
|
open_file(output, "wb") {|f|
|
343
|
-
job.result_format('msgpack', f)
|
405
|
+
job.result_format('msgpack', f, &progress)
|
344
406
|
}
|
345
407
|
|
346
408
|
when 'msgpack.gz'
|
409
|
+
if output.nil?
|
410
|
+
raise ParameterConfigurationError,
|
411
|
+
"Format 'msgpack' does not support writing to stdout"
|
412
|
+
end
|
347
413
|
open_file(output, "wb") {|f|
|
348
|
-
job.result_format('msgpack.gz', f)
|
414
|
+
job.result_format('msgpack.gz', f, &progress)
|
349
415
|
}
|
350
416
|
|
351
417
|
else
|
352
418
|
raise "Unknown format #{format.inspect}"
|
353
419
|
end
|
420
|
+
|
421
|
+
# clear the progress indicator
|
422
|
+
if !output.nil?
|
423
|
+
print "\r"
|
424
|
+
print " " * (line_len + 5) + "\r"
|
425
|
+
end
|
354
426
|
end
|
355
427
|
|
356
428
|
def open_file(output, mode)
|
@@ -371,6 +443,14 @@ module Command
|
|
371
443
|
require 'yajl'
|
372
444
|
|
373
445
|
if format.nil?
|
446
|
+
|
447
|
+
# start progress indicator
|
448
|
+
start_time = last_time = Time.now.to_i
|
449
|
+
base_msg = "WARNING: the query result is being downloaded"
|
450
|
+
msg = base_msg + "\r"
|
451
|
+
line_len = msg.length
|
452
|
+
print msg
|
453
|
+
|
374
454
|
# display result in tabular format
|
375
455
|
rows = []
|
376
456
|
n_rows = 0
|
@@ -381,8 +461,21 @@ module Command
|
|
381
461
|
}
|
382
462
|
n_rows += 1
|
383
463
|
break if !limit.nil? and n_rows == limit
|
464
|
+
|
465
|
+
# progress indication
|
466
|
+
time = Time.now.to_i
|
467
|
+
if time - last_time > 5
|
468
|
+
msg = base_msg + ": #{humanize_time(time - start_time)} elapsed" + " " * 10 + "\r"
|
469
|
+
line_len = msg.length
|
470
|
+
print msg
|
471
|
+
last_time = time
|
472
|
+
end
|
384
473
|
}
|
385
474
|
|
475
|
+
# clear the progress indicator
|
476
|
+
print "\r"
|
477
|
+
print " " * (line_len + 5) + "\r"
|
478
|
+
|
386
479
|
render_opts[:max_width] = 10000
|
387
480
|
if job.hive_result_schema
|
388
481
|
render_opts[:change_fields] = job.hive_result_schema.map { |name,type| name }
|