gd_bam 0.1.30 → 0.1.31
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.
- data/lib/bam/version.rb +1 -1
- data/lib/base/taps.rb.orig +35 -0
- data/lib/cloud_connect/dsl/helpers.rb.orig +229 -0
- data/lib/generators/downloaders.rb +132 -117
- data/lib/generators/etl.rb +1 -1
- data/lib/utils/utils.rb +11 -2
- metadata +4 -2
data/lib/bam/version.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
module GoodData
|
2
|
+
module Bam
|
3
|
+
module Taps
|
4
|
+
|
5
|
+
def self.get_incremental(taps)
|
6
|
+
taps.find_all {|t| t[:direct] == false || t[:direct].nil? }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.get_salesforce(taps)
|
10
|
+
taps.find_all {|t| t[:source_type] == :salesforce}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.get_file(taps)
|
14
|
+
taps.find_all {|t| [:web, :file].include?(t[:source_type]) }
|
15
|
+
end
|
16
|
+
|
17
|
+
<<<<<<< HEAD
|
18
|
+
def self.get_deleted_records_info(taps, client)
|
19
|
+
deleted = client.modules.map {|i| {:name => i[:name], :flag => i[:replicateable]}}.reduce({}) {|memo, x| memo.merge({x[:name] => x[:flag]})}
|
20
|
+
taps.map do |t|
|
21
|
+
if t[:source_type] == :salesforce
|
22
|
+
t.merge({:has_deleted_records => deleted[t[:object]]})
|
23
|
+
else
|
24
|
+
t.merge({:has_deleted_records => false})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
=======
|
28
|
+
def self.get_box(taps)
|
29
|
+
taps.find_all {|t| [:box].include?(t[:source_type]) }
|
30
|
+
>>>>>>> Box init
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
module GoodData
|
2
|
+
module CloudConnect
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def self.property(builder, data)
|
6
|
+
builder.Property({
|
7
|
+
:id => data[:id],
|
8
|
+
:name => data[:name] || data[:id],
|
9
|
+
:value => data[:value]
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.property_file(builder, data)
|
14
|
+
builder.Property({
|
15
|
+
:id => data[:id],
|
16
|
+
:fileURL => data[:fileURL]
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
<<<<<<< HEAD
|
21
|
+
def self.create_deleted_records_meta(builder)
|
22
|
+
builder.Metadata({:id => "deleted_records_metadata"}) do |builder|
|
23
|
+
csv_metadata(builder, {
|
24
|
+
:name => "deleted_records_metadata",
|
25
|
+
:fields => [
|
26
|
+
{:type => "string", :name => "Id"},
|
27
|
+
{:type => "string", :name => "Timestamp"}
|
28
|
+
=======
|
29
|
+
def self.create_http_request_meta(builder)
|
30
|
+
builder.Metadata({:id => "http_metadata"}) do |builder|
|
31
|
+
csv_metadata(builder, {
|
32
|
+
:name => "http_metadata",
|
33
|
+
:fields => [
|
34
|
+
{:type => "string", :name => "response"},
|
35
|
+
{:type => "string", :name => "all"}
|
36
|
+
>>>>>>> Box init
|
37
|
+
]
|
38
|
+
})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.create_trash_meta(builder)
|
43
|
+
builder.Metadata({:id => "trash_metadata"}) do |builder|
|
44
|
+
csv_metadata(builder, {
|
45
|
+
:name => "trash_metadata",
|
46
|
+
:fields => [{:type => "string", :name => "all"}]
|
47
|
+
})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.save_metadata(filename, data)
|
52
|
+
dirname = File.dirname(filename)
|
53
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
54
|
+
|
55
|
+
File.open(filename, "w") do |file|
|
56
|
+
builder = Builder::XmlMarkup.new(:target => file, :indent=>2)
|
57
|
+
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
58
|
+
csv_metadata(builder, data)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.create_moving_graph(file, options={})
|
63
|
+
source = options[:source]
|
64
|
+
target = options[:target]
|
65
|
+
operation = options[:operation]
|
66
|
+
force = options[:force] || false
|
67
|
+
|
68
|
+
File.open(file, "w") do |file|
|
69
|
+
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
70
|
+
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
71
|
+
builder.Graph({
|
72
|
+
:name => "File Copy"
|
73
|
+
}) do
|
74
|
+
builder.Global do
|
75
|
+
builder.Metadata({:id => "list_metadata"}) do |builder|
|
76
|
+
Helpers::csv_metadata(builder, {
|
77
|
+
:name => "list_metadata",
|
78
|
+
:fields => [{:name=>"filePath", :type=>"string"}]
|
79
|
+
})
|
80
|
+
end
|
81
|
+
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
82
|
+
end
|
83
|
+
builder.Phase(:number => 0) do
|
84
|
+
|
85
|
+
transformation_source = "function integer transform() {\n" + ([["filePath", "filePath"]].map {|t| "$out.0.#{t.last} = $in.0.#{t.first};"}.join("\n")) + "\nreturn OK;\n}"
|
86
|
+
Core::build_node2(builder, Nodes.file_list2(:baseURL => target, :id => "file_list", :output_mapping => transformation_source))
|
87
|
+
|
88
|
+
Core::build_node2(builder, Nodes.file_delete2(:baseURL => "${filePath}", :id => "file_delete"))
|
89
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "file_delete:0", :fromNode => "file_list:0", :metadata => "list_metadata"}))
|
90
|
+
end
|
91
|
+
builder.Phase(:number => 1) do
|
92
|
+
Core::build_node2(builder, Nodes.file_copy2({:sourcePath => source, :targetPath => target, :operation => operation, :id => "file_copy"}))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.csv_metadata(builder, description)
|
99
|
+
sf_description = description.merge({
|
100
|
+
:fieldDelimiter => ",",
|
101
|
+
:recordDelimiter => "\\n",
|
102
|
+
:type => "delimited",
|
103
|
+
})
|
104
|
+
metadata(builder, sf_description)
|
105
|
+
end
|
106
|
+
|
107
|
+
# prepares a sink for sinking into GD. This means dealing with stuff like scientific notation which is handled bu uploading as a decimal and not string
|
108
|
+
def self.sink_out_gd_metadata(metadata, sink)
|
109
|
+
metadata_fields = metadata[:fields]
|
110
|
+
sink_facts = GoodData::Bam::Sink.get_fact_fields(sink).map {|f| f[:meta]}
|
111
|
+
x = metadata_fields.map {|f| sink_facts.include?(f[:name]) ? f.merge({:type => "decimal"}) : f}
|
112
|
+
GoodData::Bam::Metadata.create(metadata.merge({:fields => x}))
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.metadata(builder, description)
|
116
|
+
builder.Record({
|
117
|
+
:fieldDelimiter => description[:fieldDelimiter],
|
118
|
+
:name => description[:name],
|
119
|
+
:recordDelimiter => description[:recordDelimiter],
|
120
|
+
:type => description[:type]
|
121
|
+
}) do |record|
|
122
|
+
description[:fields].each do |field|
|
123
|
+
builder.Field :name => field[:name], :type => field[:type] || "string", :nullable => "true"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.create_lookup_meta(builder)
|
129
|
+
builder.Metadata({:id => "lookup_metadata"}) do |builder|
|
130
|
+
csv_metadata(builder, {
|
131
|
+
:name => "lookup_metadata",
|
132
|
+
:fields => [{:type => "string", :name => "key"}, {:type => "string", :name => "value"}]
|
133
|
+
})
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.create_file_list_meta(builder)
|
138
|
+
builder.Metadata({:id => "file_list"}) do |builder|
|
139
|
+
csv_metadata(builder, {
|
140
|
+
:name => "file_list",
|
141
|
+
:fields => [
|
142
|
+
{:name => "filePath", :type => "string"},
|
143
|
+
{:name => "fileName", :type => "string"}
|
144
|
+
]
|
145
|
+
})
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.create_read_error_meta(builder)
|
150
|
+
builder.Metadata({:id => "reader_error_metadata"}) do |builder|
|
151
|
+
csv_metadata(builder, {
|
152
|
+
:name => "reader_error_metadata",
|
153
|
+
:fields => [
|
154
|
+
{:name => "line_number", :type => "integer"},
|
155
|
+
{:name => "field_number", :type => "integer"},
|
156
|
+
{:name => "record", :type => "string"},
|
157
|
+
{:name => "message", :type => "string"},
|
158
|
+
{:name => "file", :type => "string"}
|
159
|
+
]
|
160
|
+
})
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.create_run_graph_failure_metadata(builder)
|
165
|
+
builder.Metadata({:id => "run_graph_failure_metadata"}) do |builder|
|
166
|
+
csv_metadata(builder, {
|
167
|
+
:name => "run_graph_failure_metadata",
|
168
|
+
:fields => [
|
169
|
+
{:type => "string", :name => "graph"},
|
170
|
+
{:type => "string", :name => "result"},
|
171
|
+
{:type => "string", :name => "description"},
|
172
|
+
{:type => "string", :name => "message"},
|
173
|
+
{:type => "decimal", :name => "duration"}
|
174
|
+
]
|
175
|
+
})
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.create_run_graph(file, options={})
|
180
|
+
subgraphs = options[:subgraphs]
|
181
|
+
flow = options[:flow]
|
182
|
+
File.open(file, "w") do |file|
|
183
|
+
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
184
|
+
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
185
|
+
builder.Graph({
|
186
|
+
:name => "Run graph"
|
187
|
+
}) do
|
188
|
+
builder.Global do
|
189
|
+
property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
190
|
+
property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
|
191
|
+
create_trash_meta(builder)
|
192
|
+
create_lookup_meta(builder)
|
193
|
+
|
194
|
+
end
|
195
|
+
phase = 0
|
196
|
+
subgraphs.each do |subgraph|
|
197
|
+
name = GoodData::Bam::Step.step_name(GoodData::Bam::Graph.create(:path => subgraph))
|
198
|
+
# Pathname(subgraph).basename.to_s.chomp(Pathname(subgraph).extname)
|
199
|
+
builder.Phase(:number => phase+1) do
|
200
|
+
id1 = GoodData::CloudConnect::Nodes.get_id
|
201
|
+
id2 = GoodData::CloudConnect::Nodes.get_id
|
202
|
+
ctl = "function integer generate() {$out.0.all = \"FLOW=#{flow}\";return OK;}"
|
203
|
+
Core::build_node2(builder, Nodes.data_generator2({:name => id1, :id => id1, :generate => ctl}))
|
204
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id2}:0", :fromNode => "#{id1}:0", :metadata => "trash_metadata"}))
|
205
|
+
Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id2}", :fileURL => "params.prm", :outputFieldNames => "false", :quotedStrings => "false"}))
|
206
|
+
end
|
207
|
+
builder.Phase(:number => phase+2) do
|
208
|
+
|
209
|
+
id1 = GoodData::CloudConnect::Nodes.get_id
|
210
|
+
id2 = GoodData::CloudConnect::Nodes.get_id
|
211
|
+
ctl = "function integer generate() {$out.0.all = \"NAME=#{name}\";return OK;}"
|
212
|
+
Core::build_node2(builder, Nodes.data_generator2({:name => id1, :id => id1, :generate => ctl}))
|
213
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id2}:0", :fromNode => "#{id1}:0", :metadata => "trash_metadata"}))
|
214
|
+
Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id2}", :fileURL => "params.prm", :outputFieldNames => "false", :append => "true", :quotedStrings => "false"}))
|
215
|
+
end
|
216
|
+
|
217
|
+
builder.Phase(:number => phase+3) do
|
218
|
+
Core::build_node2(builder, Nodes.run_graph2({:guiName => name, :name => name, :id => flow, :graphName => subgraph}))
|
219
|
+
end
|
220
|
+
phase += 4
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -427,9 +427,8 @@ HEREDOC
|
|
427
427
|
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
428
428
|
end
|
429
429
|
|
430
|
-
|
430
|
+
taps_memo = {}
|
431
431
|
|
432
|
-
taps_with_history = []
|
433
432
|
taps.each do |tap|
|
434
433
|
module_name = tap[:object]
|
435
434
|
dataset = tap[:id]
|
@@ -450,134 +449,154 @@ HEREDOC
|
|
450
449
|
objects_to_get = Helpers.objects_for_history(client, tap)
|
451
450
|
|
452
451
|
(tap[:fields] - [id_field, timestamp_field]).each_with_index do |field, i|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
452
|
+
f = field[:name]
|
453
|
+
|
454
|
+
selects = if (f == "CreatedDate") then
|
455
|
+
[{
|
456
|
+
:object => sf_object,
|
457
|
+
:query => "SELECT Id, CreatedDate FROM #{sf_object}",
|
458
|
+
:mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
|
459
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Value\"}},
|
460
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
461
|
+
{\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
|
462
|
+
]}}",
|
463
|
+
:mandatory => ["Id", "CreatedDate"]
|
464
|
+
}]
|
465
|
+
else
|
466
|
+
objects_to_get.reduce([]) do |memo, o|
|
467
|
+
fields = client.fields(o)
|
468
|
+
# how the history is stored does not rely on table naming convention. It is a couple of conventionsmangled together.This piece of code is trying to recognize which it is and produce the right downloader
|
469
|
+
generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|fl| fields.include?(fl)}
|
470
|
+
specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
|
471
|
+
specific_history = ["CreatedDate", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
|
472
|
+
|
473
|
+
select, mapping, mandatory = if generic_field_history && !field[:multi_currency]
|
474
|
+
# This kicks in when you have Field History type of table. There are several versions in SF. This one deals with the one that references ID of the record as Pernt Id. This is not true for opportunity, account.
|
475
|
+
[
|
476
|
+
"SELECT NewValue, CreatedDate, ParentId FROM #{o} WHERE Field = '#{f}'",
|
477
|
+
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
478
|
+
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
479
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
480
|
+
{\"xmlFieldMapping\":{\"name\":\"ParentId\",\"label\":\"ParentId\",\"xmlPath\":\"ParentId\",\"metadataField\":\"Id\"}}
|
481
|
+
]}}",
|
482
|
+
["ParentId", "NewValue", "CreatedDate"]
|
483
|
+
]
|
484
|
+
elsif (specific_field_history && !field[:multi_currency])
|
485
|
+
# This is like the previous with the difference that it specifically names the id of the record. Like OpportunityId, AccountId, etc.
|
486
|
+
[
|
487
|
+
"SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
|
488
|
+
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
489
|
+
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
490
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
491
|
+
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
492
|
+
]}}",
|
493
|
+
["#{sf_object}Id", "NewValue", "CreatedDate"]
|
494
|
+
]
|
495
|
+
elsif specific_history
|
496
|
+
# Specific history is the row like history. The only instance I know of is OpportunityHistory.
|
497
|
+
if fields.include?(f)
|
490
498
|
[
|
491
|
-
"SELECT
|
499
|
+
(field[:multi_currency] ? "SELECT convertCurrency(#{f}), CreatedDate, #{sf_object}Id FROM #{o}" : "SELECT #{f}, CreatedDate, #{sf_object}Id FROM #{o}"),
|
492
500
|
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
493
|
-
{\"xmlFieldMapping\":{\"name\":\"
|
501
|
+
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
494
502
|
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
495
503
|
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
496
504
|
]}}",
|
497
|
-
["#{sf_object}Id",
|
505
|
+
["#{sf_object}Id", f, "CreatedDate"]
|
498
506
|
]
|
499
|
-
elsif specific_history
|
500
|
-
# Specific history is the row like history. The only instance I know of is OpportunityHistory.
|
501
|
-
if fields.include?(f)
|
502
|
-
[
|
503
|
-
(field[:multi_currency] ? "SELECT convertCurrency(#{f}), CreatedDate, #{sf_object}Id FROM #{o}" : "SELECT #{f}, CreatedDate, #{sf_object}Id FROM #{o}"),
|
504
|
-
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
505
|
-
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
506
|
-
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
507
|
-
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
508
|
-
]}}",
|
509
|
-
["#{sf_object}Id", f, "CreatedDate"]
|
510
|
-
]
|
511
|
-
else
|
512
|
-
[nil, nil, nil]
|
513
|
-
end
|
514
|
-
else
|
515
|
-
puts "Warning: Unrecognized fields configuration for historization in SF for #{o}"
|
516
|
-
end
|
517
|
-
if select.nil?
|
518
|
-
memo
|
519
507
|
else
|
520
|
-
|
521
|
-
:object => o,
|
522
|
-
:query => select,
|
523
|
-
:mapping => mapping,
|
524
|
-
:mandatory => mandatory
|
525
|
-
}])
|
508
|
+
[nil, nil, nil]
|
526
509
|
end
|
510
|
+
else
|
511
|
+
puts "Warning: Unrecognized fields configuration for historization in SF for #{o}"
|
527
512
|
end
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
{\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
|
538
|
-
{\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
|
539
|
-
]}}",
|
540
|
-
:mandatory => ["Id", f, "SystemModstamp"]
|
541
|
-
}])
|
542
|
-
selects.each_with_index do |obj, i|
|
543
|
-
# binding.pry if f== "CreatedDate"
|
544
|
-
o = obj[:object]
|
545
|
-
mapping = obj[:mapping]
|
546
|
-
select = obj[:query]
|
547
|
-
mandatory = obj[:mandatory]
|
548
|
-
# puts "#{f}_#{o}_reader:0 -> #{f}_#{sf_object}_gather:#{i}"
|
549
|
-
|
550
|
-
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_#{i}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
|
551
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_#{i}_reader:0", :metadata => "data_metadata"}))
|
513
|
+
if select.nil?
|
514
|
+
memo
|
515
|
+
else
|
516
|
+
memo.concat([{
|
517
|
+
:object => o,
|
518
|
+
:query => select,
|
519
|
+
:mapping => mapping,
|
520
|
+
:mandatory => mandatory
|
521
|
+
}])
|
552
522
|
end
|
553
|
-
|
554
|
-
|
555
|
-
|
523
|
+
end
|
524
|
+
end
|
525
|
+
unless selects.empty?
|
526
|
+
# binding.pry if f== "CreatedDate"
|
527
|
+
# taps_with_history.concat([tap])
|
528
|
+
selects = selects.concat([{
|
529
|
+
:object => sf_object,
|
530
|
+
:query => (field[:multi_currency] ? "SELECT Id, convertCurrency(#{f}), SystemModstamp FROM #{sf_object}" : "SELECT Id, #{f}, SystemModstamp FROM #{sf_object}"),
|
531
|
+
:mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
|
532
|
+
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
533
|
+
{\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
|
534
|
+
{\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
|
535
|
+
]}}",
|
536
|
+
:mandatory => ["Id", f, "SystemModstamp"]
|
537
|
+
}])
|
538
|
+
|
539
|
+
taps_memo["#{tap[:id]}:#{f}"] = {
|
540
|
+
:tap => tap,
|
541
|
+
:field => f,
|
542
|
+
:selects => selects
|
543
|
+
}
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
556
547
|
|
557
|
-
|
558
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_copy:0", :fromNode => "#{f}_#{sf_object}_sort:0", :metadata => "data_metadata"}))
|
548
|
+
phase = 1
|
559
549
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
550
|
+
binding.pry
|
551
|
+
taps_memo.values.each_slice(6).to_a.each do |slice|
|
552
|
+
builder.Phase(:number => phase +=1) do
|
553
|
+
slice.each do |field|
|
554
|
+
# taps_memo.each do |key, field|
|
555
|
+
f = field[:field]
|
556
|
+
sf_object = field[:tap][:object]
|
557
|
+
selects = field[:selects]
|
558
|
+
selects.each_with_index do |obj, i|
|
559
|
+
o = obj[:object]
|
560
|
+
mapping = obj[:mapping]
|
561
|
+
select = obj[:query]
|
562
|
+
mandatory = obj[:mandatory]
|
563
|
+
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_#{i}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
|
564
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_#{i}_reader:0", :metadata => "data_metadata"}))
|
565
|
+
end
|
566
|
+
Core::build_node2(builder, Nodes.gather2({:name => "#{f} Gather", :id => "#{f}_#{sf_object}_gather"}))
|
567
|
+
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{f}_#{sf_object}_sort", :id => "#{f}_#{sf_object}_sort"}))
|
568
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_sort:0", :fromNode => "#{f}_#{sf_object}_gather:0", :metadata => "data_metadata"}))
|
564
569
|
|
565
|
-
|
570
|
+
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{f}_#{sf_object}_copy"}))
|
571
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_copy:0", :fromNode => "#{f}_#{sf_object}_sort:0", :metadata => "data_metadata"}))
|
566
572
|
|
567
|
-
|
568
|
-
Core::build_node2(builder, Nodes.
|
573
|
+
if s3_backup
|
574
|
+
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{f}_#{sf_object} s3 Writer", :id => "#{f}_#{sf_object}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{sf_object}/#{f}_#{sf_object}_\`date2long(today())\`", :outputFieldNames => true}))
|
575
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_s3:0", :fromNode => "#{f}_#{sf_object}_copy:1", :metadata => "data_metadata"}))
|
576
|
+
end
|
569
577
|
|
570
|
-
|
578
|
+
transform = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
|
579
|
+
|
580
|
+
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "#{f}_#{sf_object}_reformat", :transformation => transform}))
|
581
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_reformat:0", :fromNode => "#{f}_#{sf_object}_copy:0", :metadata => "data_metadata"}))
|
571
582
|
|
572
|
-
# Core::build_node2(builder, Nodes.trash2({:name => "#{f}_#{sf_object}_es", :id => "#{f}_#{sf_object}_es", :debugPrint => true}))
|
573
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_es:0", :fromNode => "#{f}_#{sf_object}_reformat:0", :metadata => "es_metadata"}))
|
574
|
-
end
|
575
583
|
end
|
576
584
|
end
|
577
585
|
end
|
578
586
|
|
579
|
-
|
587
|
+
taps_memo.each do |key, field|
|
588
|
+
builder.Phase(:number => phase +=1) do
|
589
|
+
tap = field[:tap]
|
590
|
+
file = field[:tap][:id]
|
591
|
+
sf_object = field[:tap][:object]
|
592
|
+
f = field[:field]
|
593
|
+
Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{f}_#{sf_object}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json({:type => :tap, :id => tap[:id], :fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => f, :meta => "Value"}]}).to_json}))
|
594
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_es:0", :fromNode => "#{f}_#{sf_object}_reformat:0", :metadata => "es_metadata"}))
|
595
|
+
end
|
596
|
+
end
|
580
597
|
|
598
|
+
taps_memo.values.uniq_by {|x| x[:tap][:id]}.each do |field_tap|
|
599
|
+
tap = field_tap[:tap]
|
581
600
|
# Download the Deleted records for these taps. since we will not have a chance to download them later
|
582
601
|
|
583
602
|
if tap[:has_deleted_records]
|
@@ -652,7 +671,7 @@ HEREDOC
|
|
652
671
|
:graph_to_run => "graphs/#{id}_download.grf"
|
653
672
|
})
|
654
673
|
create_incremental_file_downloading_graph(home + "#{tap[:id]}_download.grf", [tap], params)
|
655
|
-
|
674
|
+
|
656
675
|
end
|
657
676
|
end
|
658
677
|
|
@@ -681,6 +700,7 @@ HEREDOC
|
|
681
700
|
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
682
701
|
Helpers::create_lookup_meta(builder)
|
683
702
|
taps.each do |tap|
|
703
|
+
|
684
704
|
module_name = tap[:object]
|
685
705
|
file = tap[:id] || module_name
|
686
706
|
|
@@ -710,7 +730,6 @@ HEREDOC
|
|
710
730
|
dataset = file || module_name
|
711
731
|
source_file = tap[:source]
|
712
732
|
|
713
|
-
|
714
733
|
has_timestamp = GoodData::Bam::Tap.has_output_field?(tap, "Timestamp")
|
715
734
|
timestamp_field = GoodData::Bam::Tap.find_output_field(tap, "Timestamp")
|
716
735
|
id_field = GoodData::Bam::Tap.find_output_field(tap, "Id")
|
@@ -725,17 +744,13 @@ HEREDOC
|
|
725
744
|
end
|
726
745
|
stuff = mapping + add.join(",") + "]}}"
|
727
746
|
|
728
|
-
|
729
|
-
|
730
|
-
Core::build_node2(builder, Nodes.reader2({:name => "#{file} File Reader", :id => "#{file}_reader", :fileURL => "${FILE}"}))
|
747
|
+
Core::build_node2(builder, Nodes.reader2(Utils.merge_only_values({:name => "#{file} File Reader", :id => "#{file}_reader", :fileURL => "${FILE}"}, tap, [:charset])))
|
731
748
|
es_transformation_source = if has_timestamp
|
732
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\")
|
749
|
+
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
|
733
750
|
else
|
734
751
|
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = long2date(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"
|
735
752
|
end
|
736
753
|
|
737
|
-
# build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_reformat", :transformation => transformation_source}))
|
738
|
-
|
739
754
|
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
|
740
755
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_copy:0", :fromNode => "#{file}_reader:0", :metadata => "#{file}_source_metadata"}))
|
741
756
|
Core::build_node2(builder, Nodes.writer2({:enabled => "disabled", :name => "#{file} CSV Writer", :id => "#{file}_csv", :fileURL => "data/#{dataset.downcase}.csv", :outputFieldNames => "true"}))
|
data/lib/generators/etl.rb
CHANGED
@@ -191,7 +191,7 @@ HEREDOC
|
|
191
191
|
end
|
192
192
|
|
193
193
|
builder.Phase(:number => 0) do
|
194
|
-
Core::build_node2(builder, Nodes.reader2({:name => "reader", :id => "reader", :fileURL => tap[:source]
|
194
|
+
Core::build_node2(builder, Nodes.reader2(Utils.merge_only_values({:name => "reader", :id => "reader", :fileURL => tap[:source]}, tap, [:charset])))
|
195
195
|
|
196
196
|
Core::build_node2(builder, Nodes.copy2({:name => "copy", :id => "copy"}))
|
197
197
|
Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "reader:0", :metadata => "file_metadata"}))
|
data/lib/utils/utils.rb
CHANGED
@@ -61,6 +61,15 @@ module GoodData
|
|
61
61
|
keys.all? {|key| !params[:additional_params][key].blank?}
|
62
62
|
end
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
def self.merge_only_values(merge_onto, data, keys=[])
|
65
|
+
filtered_data = data.inject({}) {|memo, k| memo[k.first] = k[1] unless k[0].blank?; memo}
|
66
|
+
if keys.empty?
|
67
|
+
merge_onto.merge(filtered_data)
|
68
|
+
else
|
69
|
+
merge_onto.merge(filtered_data.select {|key, val| keys.include?(key)})
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
66
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gd_bam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.31
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -320,9 +320,11 @@ files:
|
|
320
320
|
- lib/base/step.rb
|
321
321
|
- lib/base/tap.rb
|
322
322
|
- lib/base/taps.rb
|
323
|
+
- lib/base/taps.rb.orig
|
323
324
|
- lib/cloud_connect/dsl/cc.rb
|
324
325
|
- lib/cloud_connect/dsl/es_helpers.rb
|
325
326
|
- lib/cloud_connect/dsl/helpers.rb
|
327
|
+
- lib/cloud_connect/dsl/helpers.rb.orig
|
326
328
|
- lib/cloud_connect/dsl/nodes.rb
|
327
329
|
- lib/cloud_connect/dsl/sf_helpers.rb
|
328
330
|
- lib/cloud_connect/dsl/structure_helpers.rb
|