tableau_server_client 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 886e88eedf330cdb09d92a5fe2bd7e1452c19c9e413fb5767098376c17d03608
4
- data.tar.gz: 5884c44fc430ff3ac02fa6d94e3f5a4edc426de9597281f019694a5fb2a76ace
3
+ metadata.gz: 0e288311bd523063625df63be79cff2295f1d48b0a17c2dc8712145be68d44ec
4
+ data.tar.gz: 02db553763acd7e4de9fa06966dde66d2a92a6bcae70ed1734c16e7ddbe474bd
5
5
  SHA512:
6
- metadata.gz: 32050b19c3d0ef603e5476f879070cf3c14cdefc522beb4a4367fb33272e79c62a1a12cc65e2799a53aa6035f8c9e3ea5cd43eac3dc59c5f4db38beee53d13cb
7
- data.tar.gz: a682c5b349b0ff0a36e15535b2da7fc52a77ba2275a2c58ee0cd8d820b3a2b1f389223ed6eb446b421234c4111f4c25f2f2e6ea8ca96623a2b18ba750afbd624
6
+ metadata.gz: 8c105d2be4dd5e12fc6230fe3edc7c3927c5ed900912e8130a68cbc8dfd948b66b74ffd187a3bf8e66cc877d7edb2e0a84bd11681c11ba1f588b4c6e6dfb64dc
7
+ data.tar.gz: 66d0710f717c507e1f5e32ac7dcebbb46d6e07c9f4bc71afb9d09f181ccb9636004f1fe82bf3bf694e01bc77f2b38e9ee4ae875a31907e3df38d47732636c4fc
@@ -5,6 +5,9 @@ require 'tableau_server_client/request_url'
5
5
  require 'tableau_server_client/request_builder'
6
6
  require 'tableau_server_client/token'
7
7
  require 'tableau_server_client/paginatable_response'
8
+ require 'tempfile'
9
+ require 'zip'
10
+ require 'stringio'
8
11
 
9
12
  module TableauServerClient
10
13
 
@@ -46,6 +49,25 @@ module TableauServerClient
46
49
  def create(resource)
47
50
  end
48
51
 
52
+ def download(resource_location)
53
+ req_url = request_url("#{resource_location.path}/content", resource_location.query_params)
54
+ response = session.get req_url.to_s
55
+ type, disposition = response.headers.values_at('content-type', 'content-disposition')
56
+ case type
57
+ when 'application/xml'
58
+ return Nokogiri::XML(response.body)
59
+ when 'application/octet-stream'
60
+ Zip::InputStream.open(StringIO.new(response.body)) do |io|
61
+ while entry = io.get_next_entry
62
+ return Nokogiri::XML(io.read) if entry.name =~ /.*\.(tds|twb)/
63
+ end
64
+ raise "TDS or TWB file not found for: #{resource_location.path}"
65
+ end
66
+ else
67
+ raise "Unknown content-type: #{type}"
68
+ end
69
+ end
70
+
49
71
  def update(resource)
50
72
  session.put do |req|
51
73
  req.url request_url(resource.path).to_s
@@ -26,7 +26,7 @@ module TableauServerClient
26
26
 
27
27
  def self.location(prefix, id=nil, filter: [])
28
28
  path = [prefix, "#{resource_name}s", id].compact.join("/")
29
- Location.new(self, path, filter)
29
+ Location.new(self, path, filter.empty? ? {} : {filter: filter.join(',')})
30
30
  end
31
31
 
32
32
  def self.extract_attributes(xml)
@@ -49,6 +49,10 @@ module TableauServerClient
49
49
  @path
50
50
  end
51
51
 
52
+ def location(query_params: {})
53
+ Location.new(self, path, query_params)
54
+ end
55
+
52
56
  def site_path
53
57
  self.class.extract_site_path(path)
54
58
  end
@@ -59,21 +63,13 @@ module TableauServerClient
59
63
 
60
64
  class Location
61
65
 
62
- def initialize(klass, path, filter)
66
+ def initialize(klass, path, query_params)
63
67
  @klass = klass
64
68
  @path = path
65
- @filter = filter
66
- end
67
-
68
- attr_reader :klass, :path
69
-
70
- def filter
71
- @filter.empty? ? {} : {filter: @filter.join(",")}
69
+ @query_params = query_params
72
70
  end
73
71
 
74
- def query_params
75
- filter
76
- end
72
+ attr_reader :klass, :path, :query_params
77
73
  end
78
74
 
79
75
  class Attribute < String
@@ -49,6 +49,70 @@ module TableauServerClient
49
49
  @client.update self
50
50
  end
51
51
 
52
+ def custom_queries
53
+ relations.select {|r| r['type'] == 'text' }.map {|c| c.content }
54
+ end
55
+
56
+ def tables
57
+ tables = []
58
+ redshift_connections = named_connections.select {|c| c.class == 'redshift' }.map {|c| c.name }
59
+ relations.each do |rel|
60
+ next unless redshift_connections.include? rel['connection']
61
+ case rel['type']
62
+ when 'table'
63
+ tables << rel['table']
64
+ when 'text'
65
+ tables.concat extract_tables(rel.content)
66
+ else
67
+ next
68
+ end
69
+ end
70
+ tables.map {|t| t.gsub(/[\[\]")]/, '')}.uniq
71
+ end
72
+
73
+ private
74
+
75
+ NamedConnection = Struct.new("NamedConnections", :class, :caption, :name)
76
+ def named_connections
77
+ download.xpath('//named-connection').map do |c|
78
+ NamedConnection.new(c.first_element_child['class'], c['caption'], c['name'])
79
+ end
80
+ end
81
+
82
+ def download
83
+ @twb ||= @client.download location(query_params: {"includeExtract": "False"})
84
+ end
85
+
86
+ def relations
87
+ download.xpath('//datasources//datasource//relation')
88
+ end
89
+
90
+ def extract_tables(query)
91
+ q = query.dup
92
+ q.gsub!(/(\<\[Parameters\]\.\[.*?\]\>)/, "'\\1'")\
93
+ .gsub!(/(--[^\r\n]*)|(\/\*[\w\W]*?(?=\*\/)\*\/)/m, '')\
94
+ .gsub!(/[\t\r\n]/, ' ')\
95
+ .gsub!(/\s+/, ' ')
96
+
97
+ tables = []
98
+ may_be_table = false
99
+ q.split(' ').each do |t|
100
+ t.downcase!
101
+ if may_be_table
102
+ tables << t unless t =~ /(^select|^\(.*)/
103
+ may_be_table = false
104
+ end
105
+ if ['from', 'join'].include?(t)
106
+ may_be_table = true
107
+ end
108
+ end
109
+ tables
110
+ # ParseError with sub-query without alias name
111
+ #PgQuery.parse(no_parameter_query).tables.each do |t|
112
+ # yield t
113
+ #end
114
+ end
115
+
52
116
  end
53
117
  end
54
118
  end
@@ -1,3 +1,3 @@
1
1
  module TableauServerClient
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -29,4 +29,5 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency 'faraday', '>= 0.14.0'
30
30
  spec.add_dependency 'nokogiri', '>= 1.8.2'
31
31
  spec.add_dependency 'pry', '>= 0.11.3'
32
+ spec.add_dependency 'rubyzip', '>= 1.2.1'
32
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tableau_server_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - shimpeko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-27 00:00:00.000000000 Z
11
+ date: 2018-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.11.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubyzip
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 1.2.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 1.2.1
111
125
  description: REST API Client for Tableau Server.
112
126
  email:
113
127
  - shimpeko@swimmingpython.com