gd_bam 0.1.34 → 0.1.35
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bam/version.rb +1 -1
- data/lib/cloud_connect/dsl/helpers.rb +7 -2
- data/lib/generators/downloaders.rb +36 -17
- data/lib/generators/etl.rb +41 -4
- metadata +4 -6
- data/lib/base/taps.rb.orig +0 -35
- data/lib/cloud_connect/dsl/helpers.rb.orig +0 -229
data/lib/bam/version.rb
CHANGED
@@ -98,7 +98,7 @@ module GoodData
|
|
98
98
|
def self.sink_out_gd_metadata(metadata, sink)
|
99
99
|
metadata_fields = metadata[:fields]
|
100
100
|
sink_facts = GoodData::Bam::Sink.get_fact_fields(sink).map {|f| f[:meta]}
|
101
|
-
x = metadata_fields.map {|f| sink_facts.include?(f[:name]) ? f.merge({:type => "decimal"}) : f}
|
101
|
+
x = metadata_fields.map {|f| sink_facts.include?(f[:name]) ? f.merge({:type => "decimal", :length => 20, :scale => 3}) : f}
|
102
102
|
GoodData::Bam::Metadata.create(metadata.merge({:fields => x}))
|
103
103
|
end
|
104
104
|
|
@@ -110,7 +110,12 @@ module GoodData
|
|
110
110
|
:type => description[:type]
|
111
111
|
}) do |record|
|
112
112
|
description[:fields].each do |field|
|
113
|
-
|
113
|
+
# binding.pry if field.has_key?(:length)
|
114
|
+
cloned_field = field.clone
|
115
|
+
cloned_field[:type] = "string" if cloned_field[:type].blank?
|
116
|
+
cloned_field[:nullable] = "true" if cloned_field[:nullable].blank?
|
117
|
+
|
118
|
+
builder.Field cloned_field
|
114
119
|
end
|
115
120
|
end
|
116
121
|
end
|
@@ -38,19 +38,29 @@ module GoodData
|
|
38
38
|
function integer count() {
|
39
39
|
|
40
40
|
// This would run for the first time since we do not have anything stored in the custom properties hash
|
41
|
-
if (indexOf($in.0.key, "#{dataset}_LAST_RUN") != -1) {
|
41
|
+
//if (indexOf($in.0.key, "#{dataset}_LAST_RUN") != -1) {
|
42
42
|
return 4;
|
43
|
-
}
|
44
|
-
else {
|
45
|
-
|
46
|
-
}
|
43
|
+
//}
|
44
|
+
//else {
|
45
|
+
// return 0;
|
46
|
+
//}
|
47
47
|
}
|
48
48
|
|
49
49
|
string last_run = null;
|
50
50
|
long last_run_ts = null;
|
51
51
|
string end_date = null;
|
52
|
-
|
53
|
-
|
52
|
+
date now = today();
|
53
|
+
|
54
|
+
string p_year = date2str(now, "yyyy");
|
55
|
+
string p_month = date2str(now, "MM");
|
56
|
+
string p_day = date2str(now, "dd");
|
57
|
+
string p_hour = date2str(now, "HH");
|
58
|
+
string p_minute = date2str(now, "mm");
|
59
|
+
string p_second = date2str(now, "ss");
|
60
|
+
|
61
|
+
string now_date_concatenated = concat(p_year, '-', p_month, '-', p_day, 'T', p_hour, ':', p_minute, ':', p_second, '.000');
|
62
|
+
long now_without_milis = date2long(str2date(now_date_concatenated, "yyyy-MM-dd'T'HH:mm:ss.SSS"));
|
63
|
+
long ten_mins_ago = now_without_milis - (60L * 10L * 1000L);
|
54
64
|
|
55
65
|
|
56
66
|
function integer transform(integer idx) {
|
@@ -59,6 +69,11 @@ function integer transform(integer idx) {
|
|
59
69
|
last_run_ts = date2long(jodaStr2date(last_run, ["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC'));
|
60
70
|
}
|
61
71
|
|
72
|
+
printErr(ten_mins_ago);
|
73
|
+
printErr(date2long(now));
|
74
|
+
printErr(last_run_ts);
|
75
|
+
|
76
|
+
|
62
77
|
if (end_date == null) {
|
63
78
|
if (ten_mins_ago < last_run_ts) {
|
64
79
|
end_date = jodaDate2str(long2date(last_run_ts), "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", "en_US", 'UTC');
|
@@ -66,7 +81,7 @@ function integer transform(integer idx) {
|
|
66
81
|
end_date = jodaDate2str(long2date(ten_mins_ago), "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", "en_US", 'UTC');
|
67
82
|
}
|
68
83
|
}
|
69
|
-
|
84
|
+
|
70
85
|
if (idx == 1) {
|
71
86
|
$out.0.all = "#{dataset}_TRUNCATE_DATE=" + jodaDate2str(jodaStr2date(last_run, ["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC'), "yyyy-MM-dd HH:mm:ss", 'en_US', 'UTC');
|
72
87
|
} else if (idx == 2) {
|
@@ -74,7 +89,8 @@ function integer transform(integer idx) {
|
|
74
89
|
} else if (idx == 3) {
|
75
90
|
$out.0.all = "#{dataset}_END=" + end_date;
|
76
91
|
} else {
|
77
|
-
$out.0.all = "#{dataset}_LAST_RUN=" + end_date;
|
92
|
+
$out.0.all = "#{dataset}_LAST_RUN=" + end_date;
|
93
|
+
//+ last_run_ts + " " + ten_mins_ago;
|
78
94
|
}
|
79
95
|
|
80
96
|
return OK;
|
@@ -320,7 +336,9 @@ HEREDOC
|
|
320
336
|
es_transformation_source = if has_timestamp
|
321
337
|
"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}"
|
322
338
|
else
|
323
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp =
|
339
|
+
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = jodaStr2date(\"${#{dataset}_END}\",[\"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"], 'en_US', 'UTC', 'UTC');\nreturn OK;\n}"
|
340
|
+
|
341
|
+
|
324
342
|
end
|
325
343
|
|
326
344
|
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
|
@@ -338,7 +356,7 @@ HEREDOC
|
|
338
356
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
339
357
|
|
340
358
|
else
|
341
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_s3_reformat", :transformation => "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp =
|
359
|
+
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_s3_reformat", :transformation => "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = \"${#{dataset}_END}\";\nreturn OK;\n}"}))
|
342
360
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3_reformat:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
343
361
|
|
344
362
|
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
@@ -450,7 +468,6 @@ HEREDOC
|
|
450
468
|
|
451
469
|
(tap[:fields] - [id_field, timestamp_field]).each_with_index do |field, i|
|
452
470
|
f = field[:name]
|
453
|
-
|
454
471
|
selects = if (f == "CreatedDate") then
|
455
472
|
[{
|
456
473
|
:object => sf_object,
|
@@ -465,6 +482,7 @@ HEREDOC
|
|
465
482
|
else
|
466
483
|
objects_to_get.reduce([]) do |memo, o|
|
467
484
|
fields = client.fields(o)
|
485
|
+
fields_with_details = client.fields(sf_object, :with_details => true)
|
468
486
|
# 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
487
|
generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|fl| fields.include?(fl)}
|
470
488
|
specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
|
@@ -483,8 +501,10 @@ HEREDOC
|
|
483
501
|
]
|
484
502
|
elsif (specific_field_history && !field[:multi_currency])
|
485
503
|
# This is like the previous with the difference that it specifically names the id of the record. Like OpportunityId, AccountId, etc.
|
504
|
+
sf_field = fields_with_details.find {|sf_f| sf_f[:name] == f}
|
505
|
+
sf_field_type = sf_field[:type]
|
486
506
|
[
|
487
|
-
"SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
|
507
|
+
sf_field_type == "reference" ? "SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f.chomp('Id')}'" : "SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
|
488
508
|
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
489
509
|
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
490
510
|
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
@@ -547,7 +567,7 @@ HEREDOC
|
|
547
567
|
|
548
568
|
phase = 1
|
549
569
|
|
550
|
-
taps_memo.values.each_slice(
|
570
|
+
taps_memo.values.each_slice(4).to_a.each do |slice|
|
551
571
|
builder.Phase(:number => phase +=1) do
|
552
572
|
slice.each do |field|
|
553
573
|
# taps_memo.each do |key, field|
|
@@ -747,7 +767,7 @@ HEREDOC
|
|
747
767
|
es_transformation_source = if has_timestamp
|
748
768
|
"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}"
|
749
769
|
else
|
750
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp =
|
770
|
+
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = jodaStr2date(\"${#{dataset}_END}\",[\"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"], 'en_US', 'UTC', 'UTC');\nreturn OK;\n}"
|
751
771
|
end
|
752
772
|
|
753
773
|
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
|
@@ -757,7 +777,7 @@ HEREDOC
|
|
757
777
|
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_es_reformat", :transformation => es_transformation_source}))
|
758
778
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_reformat:0", :fromNode => "#{file}_copy:1", :metadata => "#{file}_source_metadata"}))
|
759
779
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_csv:0", :fromNode => "#{file}_copy:0", :metadata => "#{file}_source_metadata"}))
|
760
|
-
|
780
|
+
|
761
781
|
if s3_backup
|
762
782
|
if has_timestamp
|
763
783
|
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
@@ -772,7 +792,6 @@ HEREDOC
|
|
772
792
|
# Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
773
793
|
# Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
774
794
|
end
|
775
|
-
|
776
795
|
|
777
796
|
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{file} es Sort", :id => "#{file}_es_sort"}))
|
778
797
|
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_sort:0", :fromNode => "#{file}_es_reformat:0", :metadata => "#{file}_es_metadata"}))
|
data/lib/generators/etl.rb
CHANGED
@@ -144,7 +144,7 @@ function decimal deal_with_scientific_notation(string a_number) {
|
|
144
144
|
if (isnull(a_number) || a_number == "") {
|
145
145
|
return null;
|
146
146
|
} else {
|
147
|
-
return str2decimal(a_number);
|
147
|
+
return floor(str2decimal(a_number)*1000D)/1000D;
|
148
148
|
}
|
149
149
|
}
|
150
150
|
|
@@ -304,6 +304,7 @@ HEREDOC
|
|
304
304
|
end
|
305
305
|
|
306
306
|
|
307
|
+
# Skipping the one row that is added by ES
|
307
308
|
transformation_source = if Metadata::has_field?(metadata_from_es, "Snapshot")
|
308
309
|
"function integer transform() {\n" + (Tap.source_target_mappging(tap).map {|t| "$out.0.#{t.last} = $in.0.#{t.first};"}.join("\n")) + "\n$out.0.Snapshot = date2str(dateAdd(str2date(\"1900-01-01\", \"yyyy-MM-dd\"), str2long($in.0.Snapshot), day), \"yyyy-MM-dd\");\nreturn OK;\n}"
|
309
310
|
else
|
@@ -311,17 +312,53 @@ HEREDOC
|
|
311
312
|
end
|
312
313
|
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "reformat", :transformation => transformation_source}))
|
313
314
|
Core::build_node2(builder, Nodes.edge2({:toNode => "reformat:0", :fromNode => "es:0", :metadata => "es_metadata"}))
|
315
|
+
|
316
|
+
# Filter out deleted Records
|
314
317
|
if tap[:has_deleted_records] == true
|
315
318
|
filter_deleted_function = "function integer transform() {\nif ($in.0.IsDeleted == \"true\") {return SKIP;} else {$out.0.* = $in.0.*; return OK;};\n}"
|
316
319
|
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "filter_deleted", :transformation => filter_deleted_function}))
|
317
320
|
Core::build_node2(builder, Nodes.edge2({:toNode => "filter_deleted:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
|
318
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "
|
321
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "dummy_reformat_1:0", :fromNode => "filter_deleted:0", :metadata => "output_metadata"}))
|
319
322
|
else
|
320
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "
|
323
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "dummy_reformat_1:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
|
321
324
|
end
|
322
325
|
|
326
|
+
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "dummy_reformat_1", :transformation => Nodes::MAP_ALL}))
|
327
|
+
|
328
|
+
# Propagating a value from latest snapshot to all snapshots if necessary
|
329
|
+
if tap[:propagate_latest_value_for] && !tap[:propagate_latest_value_for].empty?
|
330
|
+
|
331
|
+
retain_transform = <<HEREDOC
|
332
|
+
#{tap[:propagate_latest_value_for].map {|f| "string " + f + " = \"\";"}.join("\n")}
|
333
|
+
string id = null;
|
334
|
+
string previousId = null;
|
335
|
+
|
336
|
+
function integer transform() {
|
337
|
+
$out.0.* = $in.0.*;
|
338
|
+
id = $in.0.Id;
|
339
|
+
if (id != previousId) {
|
340
|
+
#{tap[:propagate_latest_value_for].map {|f| f + " = $in.0." + f + ";"}.join("\n")}
|
341
|
+
}
|
342
|
+
#{tap[:propagate_latest_value_for].map {|f| "$out.0." + f + " = " + f + ";"}.join("\n")}
|
343
|
+
previousId = id;
|
344
|
+
return ALL;
|
345
|
+
}
|
346
|
+
HEREDOC
|
347
|
+
fields_to_propagate = tap[:propagate_latest_value_for]
|
348
|
+
propagate_values_function = "string lastId;\nfunction integer transform() {\nif (lastId !=$in.0.Id) {$in.0.*=$out.0.*;} else {$in.0.*=$out.0.*; #{fields_to_propagate.map{|f| "$out.0.#{f} = \"XXXXX\""}.join("\n")}};lastId=$in.0.Id \nreturn OK;\n}"
|
349
|
+
Core::build_node2(builder, Nodes.sort2({:sortKey => "Id(a);Snapshot(d)", :id => "sort_for_history_retain"}));
|
350
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "sort_for_history_retain:0", :fromNode => "dummy_reformat_1:0", :metadata => "output_metadata"}))
|
351
|
+
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "retain_values_reformat", :transformation => retain_transform}))
|
352
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "retain_values_reformat:0", :fromNode => "sort_for_history_retain:0", :metadata => "output_metadata"}))
|
353
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "dummy_reformat_2:0", :fromNode => "retain_values_reformat:0", :metadata => "output_metadata"}))
|
354
|
+
else
|
355
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "dummy_reformat_2:0", :fromNode => "dummy_reformat_1:0", :metadata => "output_metadata"}))
|
356
|
+
end
|
357
|
+
|
358
|
+
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "dummy_reformat_2", :transformation => Nodes::MAP_ALL}))
|
359
|
+
|
323
360
|
Core::build_node2(builder, Nodes.copy2({:name => "Copy", :id => "copy"}))
|
324
|
-
|
361
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "dummy_reformat_2:0", :metadata => "output_metadata"}))
|
325
362
|
Core::build_node2(builder, Nodes.writer2({:name => "CSV Writer", :id => "csv", :fileURL => "${PROJECT}/data/#{tap[:id]}.csv", :outputFieldNames => "true", :makeDirs => "true"}))
|
326
363
|
Core::build_node2(builder, Nodes.edge2({:toNode => "csv:0", :fromNode => "copy:0", :metadata => "output_metadata"}))
|
327
364
|
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.35
|
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-10-
|
12
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -258,7 +258,7 @@ dependencies:
|
|
258
258
|
requirements:
|
259
259
|
- - ! '>='
|
260
260
|
- !ruby/object:Gem::Version
|
261
|
-
version: 0.0.
|
261
|
+
version: 0.0.4
|
262
262
|
type: :runtime
|
263
263
|
prerelease: false
|
264
264
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -266,7 +266,7 @@ dependencies:
|
|
266
266
|
requirements:
|
267
267
|
- - ! '>='
|
268
268
|
- !ruby/object:Gem::Version
|
269
|
-
version: 0.0.
|
269
|
+
version: 0.0.4
|
270
270
|
- !ruby/object:Gem::Dependency
|
271
271
|
name: gd_es
|
272
272
|
requirement: !ruby/object:Gem::Requirement
|
@@ -320,11 +320,9 @@ 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
|
324
323
|
- lib/cloud_connect/dsl/cc.rb
|
325
324
|
- lib/cloud_connect/dsl/es_helpers.rb
|
326
325
|
- lib/cloud_connect/dsl/helpers.rb
|
327
|
-
- lib/cloud_connect/dsl/helpers.rb.orig
|
328
326
|
- lib/cloud_connect/dsl/nodes.rb
|
329
327
|
- lib/cloud_connect/dsl/sf_helpers.rb
|
330
328
|
- lib/cloud_connect/dsl/structure_helpers.rb
|
data/lib/base/taps.rb.orig
DELETED
@@ -1,35 +0,0 @@
|
|
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
|
@@ -1,229 +0,0 @@
|
|
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
|