gd_bam 0.1.34 → 0.1.35
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/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
|