Merge pull request #1276 from nosqlbench/nosqlbench-1273-poplist

make list template work for all types, and go faster
This commit is contained in:
Jonathan Shook 2023-05-18 15:17:20 -05:00 committed by GitHub
commit 97e1bb032d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 24 deletions

View File

@ -77,11 +77,11 @@ public class ParsedOpTest {
final OpTemplate opTemplate = stmtsDocs.getOps().get(0); final OpTemplate opTemplate = stmtsDocs.getOps().get(0);
final ParsedOp parsedOp = new ParsedOp(opTemplate, cfg, List.of(), NBLabeledElement.forMap(Map.of())); final ParsedOp parsedOp = new ParsedOp(opTemplate, cfg, List.of(), NBLabeledElement.forMap(Map.of()));
assertThat(parsedOp.getAsFunctionOr("d1","invalid").apply(1L)).isEqualTo("one"); assertThat(parsedOp.getAsFunctionOr("d1", "invalid").apply(1L)).isEqualTo("one");
assertThat(parsedOp.getAsFunctionOr("s1","invalid").apply(1L)).isEqualTo("static-one"); assertThat(parsedOp.getAsFunctionOr("s1", "invalid").apply(1L)).isEqualTo("static-one");
assertThat(parsedOp.getAsFunctionOr("ps1","invalid").apply(1L)).isEqualTo("param-one"); assertThat(parsedOp.getAsFunctionOr("ps1", "invalid").apply(1L)).isEqualTo("param-one");
assertThat(parsedOp.getAsFunctionOr("puppy","invalid").apply(1L)).isEqualTo("dog"); assertThat(parsedOp.getAsFunctionOr("puppy", "invalid").apply(1L)).isEqualTo("dog");
assertThat(parsedOp.getAsFunctionOr("surname","invalid").apply(1L)).isEqualTo("yes"); assertThat(parsedOp.getAsFunctionOr("surname", "invalid").apply(1L)).isEqualTo("yes");
} }
@ -101,7 +101,7 @@ public class ParsedOpTest {
"field3-template", "pre-{dyna1}-post", "field3-template", "pre-{dyna1}-post",
"field4-map-template", Map.of( "field4-map-template", Map.of(
"subfield1-object", "{{Identity(); ToString()}}" "subfield1-object", "{{Identity(); ToString()}}"
),"field5-map-literal", Map.of( ), "field5-map-literal", Map.of(
"subfield2-literal", "LiteralValue" "subfield2-literal", "LiteralValue"
) )
), ),
@ -119,8 +119,8 @@ public class ParsedOpTest {
final LongFunction<? extends String> f1 = parsedOp.getAsRequiredFunction("field1-literal"); final LongFunction<? extends String> f1 = parsedOp.getAsRequiredFunction("field1-literal");
final LongFunction<? extends String> f2 = parsedOp.getAsRequiredFunction("field2-object"); final LongFunction<? extends String> f2 = parsedOp.getAsRequiredFunction("field2-object");
final LongFunction<? extends String> f3 = parsedOp.getAsRequiredFunction("field3-template"); final LongFunction<? extends String> f3 = parsedOp.getAsRequiredFunction("field3-template");
final LongFunction<? extends Map> f4 = parsedOp.getAsRequiredFunction("field4-map-template",Map.class); final LongFunction<? extends Map> f4 = parsedOp.getAsRequiredFunction("field4-map-template", Map.class);
final LongFunction<? extends Map> f5 = parsedOp.getAsRequiredFunction("field5-map-literal",Map.class); final LongFunction<? extends Map> f5 = parsedOp.getAsRequiredFunction("field5-map-literal", Map.class);
assertThat(f1.apply(1)).isNotNull(); assertThat(f1.apply(1)).isNotNull();
assertThat(f2.apply(2)).isNotNull(); assertThat(f2.apply(2)).isNotNull();
assertThat(f3.apply(3)).isNotNull(); assertThat(f3.apply(3)).isNotNull();
@ -159,5 +159,50 @@ public class ParsedOpTest {
assertThat(objects).isEqualTo(new Object[]{"three", "three", 3L, 3L}); assertThat(objects).isEqualTo(new Object[]{"three", "three", 3L, 3L});
} }
@Test
public void testLayeredListBinder() {
ParsedOp pc = new ParsedOp(
new OpData().applyFields(
Map.of(
"op", Map.of(
"alist", List.of(
List.of(
"item1",
"item2-{dyna1}"
),
Map.of(
"akey", "avalue",
"akey2", "a {dyna1} value2"
)
)
),
"bindings", Map.of(
"dyna1", "NumberNameToString()"
)
)
),
ConfigModel.of(ParsedOpTest.class)
.add(Param.defaultTo("testcfg", "testval"))
.asReadOnly()
.apply(Map.of()),
List.of(),
NBLabeledElement.forMap(Map.of())
);
Map<String, Object> result = pc.getTemplateMap().apply(1);
assertThat(result).isEqualTo(
Map.of(
"alist", List.of(
List.of("item1", "item2-one"),
Map.of(
"akey", "avalue",
"akey2", "a one value2"
)
)
)
);
}
} }

View File

@ -19,36 +19,58 @@ package io.nosqlbench.engine.api.templating;
import io.nosqlbench.virtdata.core.templates.CapturePoint; import io.nosqlbench.virtdata.core.templates.CapturePoint;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.LongFunction; import java.util.function.LongFunction;
public class ParsedTemplateList implements LongFunction<List<?>> { public class ParsedTemplateList implements LongFunction<List<?>> {
private final List<Object> protolist = new ArrayList<>(); private final Object[] protolist;
private final int[] dynamic_idx; private final int[] dynamic_idx;
private final LongFunction<?>[] functions; private final LongFunction<?>[] functions;
private final List<CapturePoint> captures = new ArrayList<>(); private final List<CapturePoint> captures = new ArrayList<>();
public ParsedTemplateList(List<Object> sublist, Map<String, String> bindings, List<Map<String, Object>> cfgsources) { public ParsedTemplateList(List<Object> list, Map<String, String> bindings, List<Map<String, Object>> cfgsources) {
List<LongFunction<?>> funcs = new ArrayList<>(); List<LongFunction<?>> funcs = new ArrayList<>();
List<Integer> dindexes = new ArrayList<>(); List<Integer> dindexes = new ArrayList<>();
protolist = new Object[list.size()];
for (int i = 0; i < sublist.size(); i++) { for (int i = 0; i < list.size(); i++) {
Object item = sublist.get(i); Object item = list.get(i);
Templatizer.Result result = Templatizer.make(bindings, item, null, cfgsources); Templatizer.Result result = Templatizer.make(bindings, item, null, cfgsources);
this.captures.addAll(result.getCaptures()); this.captures.addAll(result.getCaptures());
switch (result.getType()) {
case literal: if (item instanceof String string) {
protolist.add(result.getValue()); switch (result.getType()) {
break; case literal:
case bindref: protolist[i]=string;
case concat: break;
protolist.add(null); case bindref:
case concat:
funcs.add(result.getFunction());
dindexes.add(i);
}
} else if (item instanceof List sublist) {
ParsedTemplateList listTemplate = new ParsedTemplateList(sublist, bindings, cfgsources);
if (listTemplate.isStatic()) {
protolist[i]=sublist;
} else {
funcs.add(result.getFunction()); funcs.add(result.getFunction());
dindexes.add(i); dindexes.add(i);
break; }
} else if (item instanceof Map submap) {
ParsedTemplateMap mapTemplate = new ParsedTemplateMap("anonymous", submap, bindings, cfgsources);
if (mapTemplate.isStatic()) {
protolist[i]=submap;
} else {
funcs.add(result.getFunction());
dindexes.add(i);
}
} else {
protolist[i]=item;
} }
} }
this.dynamic_idx = dindexes.stream().mapToInt(Integer::intValue).toArray(); this.dynamic_idx = dindexes.stream().mapToInt(Integer::intValue).toArray();
this.functions = funcs.toArray(new LongFunction<?>[0]); this.functions = funcs.toArray(new LongFunction<?>[0]);
@ -57,12 +79,12 @@ public class ParsedTemplateList implements LongFunction<List<?>> {
@Override @Override
public List<?> apply(long value) { public List<?> apply(long value) {
List<Object> list = new ArrayList<>(protolist); Object[] resultAry=new Object[protolist.length];
System.arraycopy(protolist,0,resultAry,0,protolist.length);
for (int i = 0; i < dynamic_idx.length; i++) { for (int i = 0; i < dynamic_idx.length; i++) {
Object obj = functions[i].apply(value); resultAry[dynamic_idx[i]]=functions[i].apply(value);
list.set(dynamic_idx[i], obj);
} }
return list; return Arrays.asList(resultAry);
} }
public boolean isStatic() { public boolean isStatic() {