Skip to content

Commit 574be65

Browse files
authored
Support Venice Primitive keys (#83)
* Support Venice Primitive keys & add tests * Fix template reuse
1 parent 1dd5c65 commit 574be65

File tree

8 files changed

+97
-7
lines changed

8 files changed

+97
-7
lines changed

deploy/samples/venicedb.yaml

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ spec:
2020
connector = venice
2121
storeName = {{table}}
2222
partial-update-mode = true
23-
key.fields-prefix = KEY_
24-
key.fields = {{keys}}
23+
key.fields-prefix = {{keyPrefix:}}
24+
key.fields = {{keys:KEY}}
25+
key.type = {{keyType:PRIMITIVE}}
2526
value.fields-include: EXCEPT_KEY

hoptimator-k8s/src/main/java/com/linkedin/hoptimator/k8s/K8sConnector.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class K8sConnector implements Connector<Source> {
2828
@Override
2929
public Map<String, String> configure(Source source) throws SQLException {
3030
Template.Environment env =
31-
Template.Environment.EMPTY.with("name", source.database() + "-" + source.table().toLowerCase(Locale.ROOT))
31+
new Template.SimpleEnvironment().with("name", source.database() + "-" + source.table().toLowerCase(Locale.ROOT))
3232
.with("database", source.database())
3333
.with("table", source.table())
3434
.with(source.options());

hoptimator-k8s/src/main/java/com/linkedin/hoptimator/k8s/K8sJobDeployer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class K8sJobDeployer extends K8sYamlDeployer<Job> {
2626
@Override
2727
public List<String> specify(Job job) throws SQLException {
2828
Function<SqlDialect, String> sql = job.sql();
29-
Template.Environment env = Template.Environment.EMPTY.with("name",
29+
Template.Environment env = new Template.SimpleEnvironment().with("name",
3030
job.sink().database() + "-" + job.sink().table().toLowerCase(Locale.ROOT))
3131
.with("database", job.sink().database())
3232
.with("schema", job.sink().schema())

hoptimator-k8s/src/main/java/com/linkedin/hoptimator/k8s/K8sSourceDeployer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class K8sSourceDeployer extends K8sYamlDeployer<Source> {
2424
@Override
2525
public List<String> specify(Source source) throws SQLException {
2626
Template.Environment env =
27-
Template.Environment.EMPTY.with("name", source.database() + "-" + source.table().toLowerCase(Locale.ROOT))
27+
new Template.SimpleEnvironment().with("name", source.database() + "-" + source.table().toLowerCase(Locale.ROOT))
2828
.with("database", source.database())
2929
.with("schema", source.schema())
3030
.with("table", source.table())

hoptimator-util/src/main/java/com/linkedin/hoptimator/util/Template.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public SimpleTemplate(String template) {
162162
public String render(Environment env) {
163163
StringBuffer sb = new StringBuffer();
164164
Pattern p =
165-
Pattern.compile("([\\s\\-\\#]*)\\{\\{\\s*([\\w_\\-\\.]+)\\s*(:([\\w_\\-\\.]+))?\\s*((\\w+\\s*)*)\\s*\\}\\}");
165+
Pattern.compile("([\\s\\-\\#]*)\\{\\{\\s*([\\w_\\-\\.]+)\\s*(:([\\w_\\-\\.]*))?\\s*((\\w+\\s*)*)\\s*\\}\\}");
166166
Matcher m = p.matcher(template);
167167
while (m.find()) {
168168
String prefix = m.group(1);

hoptimator-util/src/main/java/com/linkedin/hoptimator/util/planner/PipelineRel.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.calcite.util.Litmus;
2020
import org.apache.calcite.util.Pair;
2121

22+
import com.google.common.annotations.VisibleForTesting;
2223
import com.google.common.collect.ImmutableList;
2324

2425
import com.linkedin.hoptimator.Deployable;
@@ -44,6 +45,8 @@ public interface PipelineRel extends RelNode {
4445

4546
Convention CONVENTION = new Convention.Impl("PIPELINE", PipelineRel.class);
4647
String KEY_OPTION = "keys";
48+
String KEY_PREFIX_OPTION = "keyPrefix";
49+
String KEY_TYPE_OPTION = "keyType";
4750
String KEY_PREFIX = "KEY_";
4851

4952
void implement(Implementor implementor) throws SQLException;
@@ -95,7 +98,8 @@ public void setSink(String database, List<String> path, RelDataType rowType, Map
9598
this.sinkOptions = addKeysAsOption(options, rowType);
9699
}
97100

98-
private Map<String, String> addKeysAsOption(Map<String, String> options, RelDataType rowType) {
101+
@VisibleForTesting
102+
static Map<String, String> addKeysAsOption(Map<String, String> options, RelDataType rowType) {
99103
Map<String, String> newOptions = new LinkedHashMap<>(options);
100104

101105
RelDataType flattened = DataTypeUtils.flatten(rowType, new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT));
@@ -104,12 +108,15 @@ private Map<String, String> addKeysAsOption(Map<String, String> options, RelData
104108
if (newOptions.containsKey(KEY_OPTION)) {
105109
return newOptions;
106110
}
111+
107112
String keyString = flattened.getFieldList().stream()
108113
.map(x -> x.getName().replaceAll("\\$", "_"))
109114
.filter(name -> name.startsWith(KEY_PREFIX))
110115
.collect(Collectors.joining(";"));
111116
if (!keyString.isEmpty()) {
112117
newOptions.put(KEY_OPTION, keyString);
118+
newOptions.put(KEY_PREFIX_OPTION, KEY_PREFIX);
119+
newOptions.put(KEY_TYPE_OPTION, "RECORD");
113120
}
114121
return newOptions;
115122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.linkedin.hoptimator.util;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
public class TestTemplate {
11+
12+
@Test
13+
public void testRender() {
14+
Template.Environment env = new Template.SimpleEnvironment()
15+
.with("name", "name")
16+
.with("nameUpper", "name")
17+
.with("nameLower", "NAME")
18+
.with("multiline", "1\n2\n3\n")
19+
.with("multilineUpper", "a\nb\nc\n")
20+
.with("other", "test");
21+
22+
String template = "{{keys:KEY}}\n"
23+
+ "{{keyPrefix:}}\n"
24+
+ "{{name:default}}\n"
25+
+ "{{nameUpper toUpperCase}}\n"
26+
+ "{{nameLower toLowerCase}}\n"
27+
+ "{{multiline concat}}\n"
28+
+ "{{multilineUpper concat toUpperCase}}\n"
29+
+ "{{other unknown}}\n";
30+
31+
String renderedTemplate = new Template.SimpleTemplate(template).render(env);
32+
List<String> renderedTemplates = Arrays.asList(renderedTemplate.split("\n"));
33+
assertEquals(8, renderedTemplates.size());
34+
assertEquals("KEY", renderedTemplates.get(0));
35+
assertEquals("", renderedTemplates.get(1));
36+
assertEquals("name", renderedTemplates.get(2));
37+
assertEquals("NAME", renderedTemplates.get(3));
38+
assertEquals("name", renderedTemplates.get(4));
39+
assertEquals("123", renderedTemplates.get(5));
40+
assertEquals("ABC", renderedTemplates.get(6));
41+
assertEquals("test", renderedTemplates.get(7));
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.linkedin.hoptimator.util.planner;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import org.apache.calcite.rel.type.RelDataTypeFactory;
7+
import org.apache.calcite.rel.type.RelDataTypeSystem;
8+
import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
9+
import org.apache.calcite.sql.type.SqlTypeName;
10+
import org.junit.jupiter.api.Test;
11+
12+
import static com.linkedin.hoptimator.util.planner.PipelineRel.Implementor.addKeysAsOption;
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertTrue;
15+
16+
public class TestPipelineRel {
17+
18+
@Test
19+
public void testKeyOptions() {
20+
RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
21+
RelDataTypeFactory.Builder primitiveKeyBuilder = new RelDataTypeFactory.Builder(typeFactory);
22+
primitiveKeyBuilder.add("KEY", SqlTypeName.VARCHAR);
23+
primitiveKeyBuilder.add("intField", SqlTypeName.INTEGER);
24+
Map<String, String> keyOptions = addKeysAsOption(new HashMap<>(), primitiveKeyBuilder.build());
25+
assertTrue(keyOptions.isEmpty());
26+
27+
RelDataTypeFactory.Builder keyBuilder = new RelDataTypeFactory.Builder(typeFactory);
28+
keyBuilder.add("keyInt", SqlTypeName.INTEGER);
29+
keyBuilder.add("keyString", SqlTypeName.VARCHAR);
30+
RelDataTypeFactory.Builder recordBuilder = new RelDataTypeFactory.Builder(typeFactory);
31+
recordBuilder.add("intField", SqlTypeName.INTEGER);
32+
recordBuilder.add("KEY", keyBuilder.build());
33+
keyOptions = addKeysAsOption(new HashMap<>(), recordBuilder.build());
34+
assertEquals(3, keyOptions.size());
35+
assertEquals("KEY_keyInt;KEY_keyString", keyOptions.get("keys"));
36+
assertEquals("KEY_", keyOptions.get("keyPrefix"));
37+
assertEquals("RECORD", keyOptions.get("keyType"));
38+
}
39+
}

0 commit comments

Comments
 (0)