# coding: utf-8 module Dag module CLI class Table < SubCommand include Dag::CLI::Utils::NumberToHuman desc 'list ([DB])', 'Tables list name/location/comment/created_at' def list(database = nil) headers = %w(database table location comment created_at) rows = [] handle_api_failure { if database open_client.database(database).tables.each do |table| rows << [ table.db_name, table.name, table.location, table.comment, time_format(table.created_at) ] end else open_client.databases.each do |db| db.tables.each do |table| rows << [ table.db_name, table.name, table.location, table.comment, time_format(table.created_at) ] end end end } terminal_table(rows, headers: headers) end desc 'info [DB] [TABLE]', 'Table info database/table/schema/location/comment/created_at' def info(database, table) headers = %w(item info) rows = [] tbl = handle_api_failure do open_client.database(database).table(table) end rows << ["name", tbl.name] rows << ["format", tbl.format] rows << ["schema", tbl.schema] rows << ["location", tbl.location] rows << ["comment", tbl.comment] rows << ["created_at", time_format(tbl.created_at)] rows << ["modified_at", time_format(tbl.modified_at)] terminal_table(rows, headers: headers, max_width: Float::INFINITY) end desc 'create [DB] [TABLE]', 'Create table' option :format, type: :string, aliases: '-f', desc: "format [csv/tsv/json/json_agent]" option :comment, type: :string, desc: "table comment" option :schema, type: :string, aliases: '-s', desc: "table schema" def create(database, table) params = {} params.merge!({ format: options[:format] }) if options[:format] params.merge!({ comment: options[:comment] }) if options[:comment] params.merge!({ schema: options[:schema] }) if options[:schema] tbl = handle_api_failure do open_client.create_table(database, table, params) end say_status "Create table", tbl.name end desc 'update [DB] [TABLE]', 'Update table' option :format, type: :string, aliases: '-f', desc: "format [csv/tsv/json/json_agent]" option :comment, type: :string, desc: "table comment" def update(database, table) params = {} params.merge!({ format: options[:format] }) if options[:format] params.merge!({ comment: options[:comment] }) if options[:comment] tbl = handle_api_failure do open_client.database(database).table(table).update(params) end say_status "Update table", tbl.name end desc 'delete [DB] [TABLE]', 'Delete Table' def delete(database, table) handle_api_failure do open_client.database(database).table(table).delete end say_status "Delete table", table end desc 'split [DB] [TABLE]', 'Split objects into table' option 'input-objects', type: :array, aliases: '-i', desc: "input objects", required: true option :format, type: :string, aliases: '-f', desc: "format [csv/tsv/json]", required: true option :comment, type: :string, desc: "table comment" def split(database, table) params = { input_format: options[:format], input_object_keys: options['input-objects'] } params.merge!({ comment: options[:comment] }) if options[:comment] job = handle_api_failure do db = open_client.database(database) db.split(table, params) end say_status "Accepted split", "job_id: #{job.id}" end desc 'size [DB] [TABLE]', 'data size of table' option :sample, type: :numeric, aliases: '-s', desc: "Guess Compress Ratio by sample N objects", default: 0 def size(database, table) res=[{:Title=>"Total", :Objects=>0, :Size=>0}, {:Title=>"Gzip-ed", :Objects=>0, :Size=>0}, {:Title=>"Skipped", :Objects=>0, :Size=>0}] bucket = client.buckets[database] rows = handle_api_failure{ bucket.objects.where(prefix: table, delimiter: nil) } ckeys=[] rows.each{|r| if [".", "_"].include?(File.basename(r.name)[0]) || r.name.end_with?("_$folder$") res[2][:Objects]+=1 res[2][:Size]+=r.size next end res[0][:Objects]+=1 res[0][:Size]+=r.size if r.name.end_with? ".gz" ckeys << [r.size, r.name] res[1][:Objects]+=1 res[1][:Size]+=r.size end } ucsz = 0 csz = 0 ckeys.sample(options[:sample]).each{|k| d = bucket.objects[k[1]].read(-4..-1) csz += k[0] ucsz += d.unpack("V")[0] } fields=[:Title, :Objects, :Size] if csz!=0 res[1]["Ratio%"]="%.2f" %[csz*100.0/ucsz] unc=(res[1][:Size]/(csz*1.0/ucsz)).to_i res[1][:Uncompressed]=number_to_human(unc) res[0][:Uncompressed]=number_to_human(res[0][:Size]-res[1][:Size]+unc) fields << "Ratio%" fields << :Uncompressed end res.each{|m| m[:Size]=number_to_human(m[:Size]) } terminal_table res, fields: fields end end end end