-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSurrogateKeysFancy
87 lines (76 loc) · 2.88 KB
/
SurrogateKeysFancy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#ifndef ATTRIBUTION_CONVERGENCE_DATA_MANAGEMENT_BACKEND_SURROGATE_KEY_GENERATOR_H_
#define ATTRIBUTION_CONVERGENCE_DATA_MANAGEMENT_BACKEND_SURROGATE_KEY_GENERATOR_H_
#include <initializer_list>
#include <iterator>
#include <string>
#include <type_traits>
#include <vector>
#include "base/integral_types.h"
#include "base/template_util.h"
#include "storage/googlesql/public/functions/convert_string.h"
#include "strings/join.h"
#include "strings/stringpiece.h"
#include "util/hash/fingerprint2011.h"
namespace attribution {
namespace convergence {
namespace data_management {
namespace backend {
static constexpr char kSurrogateKeyDelimiter[] = "_";
namespace internal {
// has_const_iterator copied from:
// https://cs.corp.google.com/piper///depot/google3/ads/gpa/serving/mixer/unified/util/debug-string-helper.h?rcl=99247400&l=51
//
// SFINAE test for const_iterator member type, i.e. collection types. The value
// would be non-zero if type T has typedef-ed const_iterator.
template <typename T>
struct has_const_iterator {
template <typename C>
static base::small_ tester(typename C::const_iterator*);
template <typename C>
static base::big_ tester(...);
static const bool value = sizeof(tester<T>(nullptr)) == sizeof(base::small_);
};
} // namespace internal
// Convert arithmetic types to GoogleSql string.
template <typename T>
typename std::enable_if<std::is_integral<T>::value, string>::type
ConvertToStringForSurrogateKey(T arg) {
string result;
::googlesql::functions::NumericToString(arg, &result, nullptr);
return result;
}
// GoogleSql string overload for string family.
inline string ConvertToStringForSurrogateKey(StringPiece arg) {
return arg.as_string();
}
// Generates surrogate key for given list of arguments.
// Algorithm: FingerPrint2011(join(FingerPrint2011(args...), "_"))
//
// Example:
// uint64 surrogate_key = GenerateSurrogateKey("Hello", 123, 343.12);
template <typename... T>
uint64 GenerateSurrogateKey(const T&... args) {
return Fingerprint2011(::strings::Join(
{Fingerprint2011(ConvertToStringForSurrogateKey(args))...},
kSurrogateKeyDelimiter));
}
// Generates Surrogate key overload for input type of Container<T>. A type is
// considered container if it has const_iterator.
template <typename Container>
typename std::enable_if<internal::has_const_iterator<Container>::value,
uint64>::type
GenerateSurrogateKey(const Container& vec) {
using std::begin;
using std::end;
std::vector<uint64> fingerprints;
for (auto it = begin(vec); it != end(vec); ++it) {
fingerprints.push_back(
Fingerprint2011(ConvertToStringForSurrogateKey(*it)));
}
return Fingerprint2011(::strings::Join(fingerprints, kSurrogateKeyDelimiter));
}
} // namespace backend
} // namespace data_management
} // namespace convergence
} // namespace attribution
#endif // ATTRIBUTION_CONVERGENCE_DATA_MANAGEMENT_BACKEND_SURROGATE_KEY_GENERATOR_H_