checkpoint on progress, naming indirection, primary key models, where predicates

This commit is contained in:
Jonathan Shook 2022-07-13 01:48:05 -05:00
parent 3db4b88289
commit a2077e8a98
6 changed files with 134 additions and 17 deletions

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.converters.cql.exporters;
public record Binding(String name, String recipe) {
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.converters.cql.exporters;
import io.nosqlbench.converters.cql.cqlast.CqlColumnDef;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class BindingsAccumulator {
private final NamingFolio namer;
private final List<BindingsLibrary> libraries;
private final Map<String,String> accumulated = new LinkedHashMap<>();
public BindingsAccumulator(NamingFolio namer, List<BindingsLibrary> libraries) {
this.namer = namer;
this.libraries = libraries;
}
public Binding forColumn(CqlColumnDef def, String... extra) {
String name = namer.nameFor(def, extra);
for (BindingsLibrary library : libraries) {
Optional<String> bindingRecipe = library.resolveBindingsFor(def);
if (bindingRecipe.isPresent()) {
Binding newBinding = new Binding(name, bindingRecipe.get());
registerBinding(newBinding);
return newBinding;
}
}
throw new RuntimeException("Unable to find a binding for column def '" + def + "'");
}
private void registerBinding(Binding newBinding) {
accumulated.put(newBinding.name(), newBinding.recipe());
}
public Map<String,String> getAccumulatedBindings() {
return accumulated;
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.converters.cql.exporters;
import io.nosqlbench.converters.cql.cqlast.CqlColumnDef;
import java.util.Optional;
public interface BindingsLibrary {
Optional<String> resolveBindingsFor(CqlColumnDef def);
}

View File

@ -47,30 +47,28 @@ import java.util.stream.Collectors;
*/
public class CqlWorkloadExporter {
private final static Logger logger = LogManager.getLogger(CqlWorkloadExporter.class);
public final static String DEFAULT_NAMING_TEMPLATE = "[OPTYPE-][COLUMN-][TYPEDEF][-TABLE!][-KEYSPACE]";
public final static String DEFAULT_NAMING_TEMPLATE = "[OPTYPE-][COLUMN-][TYPEDEF-][TABLE!]-[KEYSPACE]";
private final Map<String, String> defaultBindings = new DefaultCqlBindings();
private final BindingsLibrary defaultBindings = new DefaultCqlBindings();
private final NamingFolio namer;
private final NamingFolio namer = new NamingFolio(DEFAULT_NAMING_TEMPLATE);
private final BindingsAccumulator bindings = new BindingsAccumulator(namer, List.of(defaultBindings));
private final CqlModel model;
private final Map<String, String> bindingsMap = new LinkedHashMap<>();
public CqlWorkloadExporter(CqlModel model) {
namer = new NamingFolio(DEFAULT_NAMING_TEMPLATE);
this.model = model;
}
public CqlWorkloadExporter(String ddl, Path srcpath) {
namer = new NamingFolio(DEFAULT_NAMING_TEMPLATE);
this.model = CqlModelParser.parse(ddl, srcpath);
}
public CqlWorkloadExporter(String ddl) {
namer = new NamingFolio(DEFAULT_NAMING_TEMPLATE);
this.model = CqlModelParser.parse(ddl, null);
}
public CqlWorkloadExporter(Path path) {
namer = new NamingFolio(DEFAULT_NAMING_TEMPLATE);
this.model = CqlModelParser.parse(path);
}
@ -122,12 +120,13 @@ public class CqlWorkloadExporter {
namer.populate(model);
Map<String, Object> workload = new LinkedHashMap<>();
workload.put("bindings", defaultBindings);
workload.put("bindings", bindingsMap);
Map<String, Object> blocks = new LinkedHashMap<>();
workload.put("blocks", blocks);
blocks.put("schema", genSchemaBlock(model));
blocks.put("rampup", genRampupBlock(model));
blocks.put("main", genMainBlock(model));
bindingsMap.putAll(bindings.getAccumulatedBindings());
return workload;
}
@ -137,7 +136,9 @@ public class CqlWorkloadExporter {
mainOpTemplates.putAll(
model.getAllTables()
.stream()
.collect(Collectors.toMap(namer::nameFor, this::genUpsertTemplate))
.collect(Collectors.toMap(
t -> namer.nameFor(t, "optype", "insert"),
this::genUpsertTemplate))
);
mainOpTemplates.putAll(
@ -201,19 +202,25 @@ public class CqlWorkloadExporter {
logger.warn("Unknown literal format for " + typeName);
}
return def.getName() + "=" + cqlLiteralFormat.format("{" + namer.nameFor(def) + "}");
Binding binding = bindings.forColumn(def);
return def.getName() + "=" + cqlLiteralFormat.format("{" + binding.name() + "}");
}
private String genUpsertTemplate(CqlTable table) {
List<CqlColumnDef> cdefs = table.getColumnDefinitions();
return "insert into " + table.getKeySpace() + "." + table.getTableName() + "\n ( "
+ cdefs.stream().map(cd -> cd.getName())
return "insert into " +
table.getKeySpace() + "." + table.getTableName() + "\n" +
" ( " + cdefs.stream().map(CqlColumnDef::getName)
.collect(Collectors.joining(" , ")) +
" )\n values\n (" +
cdefs
.stream()
.map(cd -> namer.nameFor(cd))
.map(cd -> {
Binding binding = bindings.forColumn(cd);
return binding.name();
})
.collect(Collectors.joining("},{", "{", "}"))
+ ");";
}

View File

@ -47,6 +47,10 @@ public class ElementNamer implements Function<Map<String, String>, String> {
Pattern pattern = Pattern.compile("(?<prefix>[^\\]]+)?\\[(?<section>(?<pre>.*?)(?<name>[A-Z]+)(?<required>!)?(?<post>.*?))?]");
Matcher scanner = pattern.matcher(template);
while (scanner.find()) {
if (scanner.group("prefix")!=null) {
String prefix = scanner.group("prefix");
sections.add(new Section(null, prefix, true));
}
if (scanner.group("section")!=null) {
Section section = new Section(
scanner.group("name").toLowerCase(),
@ -56,10 +60,6 @@ public class ElementNamer implements Function<Map<String, String>, String> {
scanner.group("required") != null);
sections.add(section);
}
if (scanner.group("prefix")!=null) {
String prefix = scanner.group("prefix");
sections.add(new Section(null, prefix, true));
}
}
}

View File

@ -24,6 +24,13 @@ import io.nosqlbench.nb.api.labels.Labeled;
import java.util.*;
/**
* The purpose of this class is to put all the logic/complexity of name condensing into one place.
* Basically if you have identifiers that are globally unique within the active namespace,
* <EM>WITHOUT</EM> using fully qualified names, then it is easier for users to use short names.
* For example, if you have a column named "score" which is used as an int in one table and as
* a double in another, then you must include the type information to provide two distinct identifiers
* for the purpose of mapping bindings.
*
* This will be a pre-built inverted index of all field which need to have bindings assigned.
* A field reference is presumed to be unique within the scope from which the traversal to
* the working set has a single path.