package adipe.translate;
import static com.google.common.base.Preconditions.checkNotNull;
import adipe.translate.sql.parser.DdlParser.ColumnDefinitionContext;
import adipe.translate.sql.parser.DdlParser.DataTypeContext;
import adipe.translate.sql.parser.DdlParser.ManyTableDefinitionsContext;
import adipe.translate.sql.parser.DdlParser.TableDefinitionContext;
import adipe.translate.sql.parser.DdlParser.TableElementContext;
import adipe.translate.sql.parser.DdlParser.TableElementListContext;
import adipe.translate.ra.Schema;
import adipe.translate.ra.SchemaBuilder;
import adipe.translate.sql.IntegerType;
import adipe.translate.sql.Type;
import adipe.translate.sql.VarcharType;
import adipe.translate.sql.parser.SchemaParserUtils;
// TODO add tests for the class
/**
*
* Construct a schema object from CREATE TABLE statements.
*
*/
public final class Schemas {
private final SchemaBuilder builder;
private SchemaBuilder.TableBuilder tableBuilder;
private Schemas() {
this.builder = SchemaBuilder.create();
}
/**
* @param source semicolon-separated CREATE TABLE statements (part of Data Definition Language)
* @return A schema object. Contains the name of the table and the names
* of the columns; ignores everything else, including constraints, default values etc.
* @throws RuntimeException parse error
*/
public static Schema fromDDL(String source) throws RuntimeException {
Schemas instance = new Schemas();
instance.visitManyTableDefinitionsContext(
new SchemaParserUtils().getParser(source).manyTableDefinitions()
);
return instance.builder.build();
}
private void visitManyTableDefinitionsContext(ManyTableDefinitionsContext ctx)
{
visitTableDefinition(ctx.tableDefinition());
if (ctx.manyTableDefinitions() != null) {
visitManyTableDefinitionsContext(ctx.manyTableDefinitions());
}
}
private void visitTableDefinition(TableDefinitionContext ctx) {
String tableName = ctx.tableName().getText();
tableBuilder = builder.table(tableName);
visitTableElementList(tableName, ctx.tableElementList());
}
private void visitTableElementList(String tableName, TableElementListContext ctx) {
for (TableElementContext tec : ctx.tableElement()) {
visitTableElement(tec);
}
}
/**
*
* @return the column name, or null if {@code ctx} denotes a table constraint definition
*/
private void visitTableElement(TableElementContext ctx) {
if (ctx.columnDefinition() != null) {
visitColumnDefinition(ctx.columnDefinition());
}
}
private void visitColumnDefinition(ColumnDefinitionContext ctx) {
String columnName = ctx.columnName().getText();
Type columnType = visitDataType(ctx.dataType());
tableBuilder.add(columnType, columnName);
}
private Type visitDataType(DataTypeContext dataType) {
//TODO support more types
if (dataType.characterStringType() != null) {
return VarcharType.INSTANCE;
} else {
checkNotNull(dataType.numericType());
return IntegerType.INSTANCE;
}
}
}