use of org.voltdb.compilereport.TableAnnotation in project voltdb by VoltDB.
the class CatalogSchemaTools method toSchema.
/**
* Convert a catalog into a string containing all DDL statements.
* @param catalog
* @param importLines A set of importLines, should not be mutated.
* @return String of DDL statements.
*/
public static String toSchema(Catalog catalog, Set<String> importLines) {
StringBuilder sb = new StringBuilder();
sb.append("-- This file was generated by VoltDB version ");
sb.append(VoltDB.instance().getVersionString());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
String time = sdf.format(System.currentTimeMillis());
sb.append(" on: " + time + ".\n");
sb.append("-- This file represents the current database schema.\n");
sb.append("-- Use this file as input to reproduce the current database structure in another database instance.\n");
sb.append("--\n");
sb.append(batchSpecificComments);
sb.append("-- If the schema declares Java stored procedures, be sure to load the .jar file\n");
sb.append("-- with the classes before loading the schema. For example:\n");
sb.append("--\n");
sb.append("-- LOAD CLASSES voltdb-procs.jar;\n");
sb.append("-- FILE ddl.sql;\n");
for (Cluster cluster : catalog.getClusters()) {
for (Database db : cluster.getDatabases()) {
toSchema(sb, importLines);
for (Group grp : db.getGroups()) {
toSchema(sb, grp);
}
sb.append("\n");
List<Table> viewList = new ArrayList<>();
CatalogMap<Table> tables = db.getTables();
if (!tables.isEmpty()) {
sb.append(startBatch);
for (Table table : tables) {
Object annotation = table.getAnnotation();
if (annotation != null && ((TableAnnotation) annotation).ddl != null && table.getMaterializer() != null) {
viewList.add(table);
continue;
}
toSchema(sb, table, null, CatalogUtil.isTableExportOnly(db, table), (table.getPartitioncolumn() != null ? table.getPartitioncolumn().getName() : null), CatalogUtil.getExportTargetIfExportTableOrNullOtherwise(db, table));
}
// A View cannot precede a table that it depends on in the DDL
for (Table table : viewList) {
String viewQuery = ((TableAnnotation) table.getAnnotation()).ddl;
toSchema(sb, table, viewQuery, false, null, null);
}
}
CatalogMap<Procedure> procedures = db.getProcedures();
if (!procedures.isEmpty()) {
for (Procedure proc : procedures) {
toSchema(sb, proc);
}
}
CatalogMap<Function> functions = db.getFunctions();
if (!functions.isEmpty()) {
for (Function func : functions) {
toSchema(sb, func);
}
}
if (!tables.isEmpty()) {
sb.append(endBatch);
}
}
}
if (dumpSchema) {
String ts = new SimpleDateFormat("MMddHHmmssSSS").format(new Date());
File f = new File(String.format("/tmp/canonical-%s.sql", ts));
try {
FileWriter fw = new FileWriter(f);
fw.write(sb.toString());
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
use of org.voltdb.compilereport.TableAnnotation in project voltdb by VoltDB.
the class DDLCompiler method addTableToCatalog.
private void addTableToCatalog(Database db, VoltXMLElement node, boolean isXDCR) throws VoltCompilerException {
assert node.name.equals("table");
// Construct table-specific maps
HashMap<String, Column> columnMap = new HashMap<>();
HashMap<String, Index> indexMap = new HashMap<>();
final String name = node.attributes.get("name");
// create a table node in the catalog
final Table table = db.getTables().add(name);
// set max value before return for view table
table.setTuplelimit(Integer.MAX_VALUE);
// add the original DDL to the table (or null if it's not there)
TableAnnotation annotation = new TableAnnotation();
table.setAnnotation(annotation);
// handle the case where this is a materialized view
final String query = node.attributes.get("query");
if (query != null) {
assert (query.length() > 0);
m_matViewMap.put(table, query);
}
final boolean isStream = (node.attributes.get("stream") != null);
final String streamTarget = node.attributes.get("export");
final String streamPartitionColumn = node.attributes.get("partitioncolumn");
// all tables start replicated
// if a partition is found in the project file later,
// then this is reversed
table.setIsreplicated(true);
// map of index replacements for later constraint fixup
final Map<String, String> indexReplacementMap = new TreeMap<>();
// Need the columnTypes sorted by column index.
SortedMap<Integer, VoltType> columnTypes = new TreeMap<>();
for (VoltXMLElement subNode : node.children) {
if (subNode.name.equals("columns")) {
int colIndex = 0;
for (VoltXMLElement columnNode : subNode.children) {
if (columnNode.name.equals("column")) {
addColumnToCatalog(table, columnNode, columnTypes, columnMap, m_compiler);
colIndex++;
}
}
// limit the total number of columns in a table
if (colIndex > MAX_COLUMNS) {
String msg = "Table " + name + " has " + colIndex + " columns (max is " + MAX_COLUMNS + ")";
throw m_compiler.new VoltCompilerException(msg);
}
}
if (subNode.name.equals("indexes")) {
// that refer to them.
for (VoltXMLElement indexNode : subNode.children) {
if (indexNode.name.equals("index") == false)
continue;
String indexName = indexNode.attributes.get("name");
if (indexName.startsWith(HSQLInterface.AUTO_GEN_IDX_PREFIX) == false) {
addIndexToCatalog(db, table, indexNode, indexReplacementMap, indexMap, columnMap, m_compiler);
}
}
for (VoltXMLElement indexNode : subNode.children) {
if (indexNode.name.equals("index") == false)
continue;
String indexName = indexNode.attributes.get("name");
if (indexName.startsWith(HSQLInterface.AUTO_GEN_IDX_PREFIX) == true) {
addIndexToCatalog(db, table, indexNode, indexReplacementMap, indexMap, columnMap, m_compiler);
}
}
}
if (subNode.name.equals("constraints")) {
for (VoltXMLElement constraintNode : subNode.children) {
if (constraintNode.name.equals("constraint")) {
addConstraintToCatalog(table, constraintNode, indexReplacementMap, indexMap);
}
}
}
}
// Warn user if DR table don't have any unique index.
if (isXDCR && node.attributes.get("drTable") != null && node.attributes.get("drTable").equalsIgnoreCase("ENABLE")) {
boolean hasUniqueIndex = false;
for (Index index : table.getIndexes()) {
if (index.getUnique()) {
hasUniqueIndex = true;
break;
}
}
if (!hasUniqueIndex) {
String info = String.format("Table %s doesn't have any unique index, it will cause full table scans to update/delete DR record and may become slower as table grow.", table.getTypeName());
m_compiler.addWarn(info);
}
}
table.setSignature(CatalogUtil.getSignatureForTable(name, columnTypes));
/*
* Validate that each variable-length column is below the max value length,
* and that the maximum size for the row is below the max row length.
*/
int maxRowSize = 0;
for (Column c : columnMap.values()) {
VoltType t = VoltType.get((byte) c.getType());
if (t == VoltType.STRING && (!c.getInbytes())) {
if (c.getSize() * MAX_BYTES_PER_UTF8_CHARACTER > VoltType.MAX_VALUE_LENGTH) {
throw m_compiler.new VoltCompilerException("Column " + name + "." + c.getName() + " specifies a maximum size of " + c.getSize() + " characters" + " but the maximum supported size is " + VoltType.humanReadableSize(VoltType.MAX_VALUE_LENGTH / MAX_BYTES_PER_UTF8_CHARACTER) + " characters or " + VoltType.humanReadableSize(VoltType.MAX_VALUE_LENGTH) + " bytes");
}
maxRowSize += 4 + c.getSize() * MAX_BYTES_PER_UTF8_CHARACTER;
} else if (t.isVariableLength()) {
if (c.getSize() > VoltType.MAX_VALUE_LENGTH) {
throw m_compiler.new VoltCompilerException("Column " + name + "." + c.getName() + " specifies a maximum size of " + c.getSize() + " bytes" + " but the maximum supported size is " + VoltType.humanReadableSize(VoltType.MAX_VALUE_LENGTH));
}
maxRowSize += 4 + c.getSize();
} else {
maxRowSize += t.getLengthInBytesForFixedTypes();
}
}
if (maxRowSize > MAX_ROW_SIZE) {
throw m_compiler.new VoltCompilerException("Error: Table " + name + " has a maximum row size of " + maxRowSize + " but the maximum supported row size is " + MAX_ROW_SIZE);
}
// the DDL statement for the VIEW
if (query != null) {
annotation.ddl = query;
} else {
// Get the final DDL for the table rebuilt from the catalog object
// Don't need a real StringBuilder or export state to get the CREATE for a table
annotation.ddl = CatalogSchemaTools.toSchema(new StringBuilder(), table, query, isStream, streamPartitionColumn, streamTarget);
}
}
Aggregations