package net.sourceforge.mayfly.evaluation.command; import net.sourceforge.mayfly.MayflyException; import net.sourceforge.mayfly.datastore.Column; import net.sourceforge.mayfly.datastore.ColumnNames; import net.sourceforge.mayfly.datastore.Columns; import net.sourceforge.mayfly.datastore.DataStore; import net.sourceforge.mayfly.datastore.Index; import net.sourceforge.mayfly.datastore.Schema; import net.sourceforge.mayfly.datastore.constraint.Constraints; import net.sourceforge.mayfly.util.ImmutableList; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class CreateTable extends Command { private String table; private Columns columns; private List constraints = new ArrayList(); private List indexes = new ArrayList(); public CreateTable(String table) { this.table = table; this.columns = new Columns(new ImmutableList()); } public String table() { return table; } @Override public UpdateStore update(DataStore store, String schema) { Schema updatedSchema = update(store, schema, store.schema(schema)); return new UpdateStore(store.replace(schema, updatedSchema), 0); } public Schema update(DataStore store, String schemaName, Schema schema) { Constraints constraints = makeTableConstraints(store, schemaName); return schema.createTable(table(), columns, constraints, new ImmutableList(indexes)); } private Constraints makeTableConstraints( DataStore store, String schema) { return resolveAll(store, schema, this.constraints); } private Constraints resolveAll( DataStore store, String schema, List unresolved) { checkMultiplePrimaryKeys(unresolved); ConstraintsBuilder result = new ConstraintsBuilder( store, schema, table, columns); for (Iterator iter = unresolved.iterator(); iter.hasNext();) { UnresolvedConstraint constraint = (UnresolvedConstraint) iter.next(); // TODO: using store (via the constructor) here is (I think) // subtlely wrong. In the case of // CREATE SCHEMA S1 CREATE TABLE FOO ... CREATE TABLE BAR ... // then store won't contain FOO. result.add(constraint); } return result.asConstraints(); } private void checkMultiplePrimaryKeys(List unresolved) { boolean havePrimaryKey = false; for (Iterator iter = unresolved.iterator(); iter.hasNext();) { UnresolvedConstraint constraint = (UnresolvedConstraint) iter.next(); if (constraint instanceof UnresolvedPrimaryKey) { if (havePrimaryKey) { /** {@link Constraints#checkOnlyOnePrimaryKey(ImmutableList)} doesn't give an error message which is quite good enough for us, at least not yet. */ throw new MayflyException("attempt to define more than " + "one primary key for table " + table); } havePrimaryKey = true; } } } public void addColumn(Column column) { columns = columns.with(column); } public void addConstraint(UnresolvedConstraint constraint) { constraints.add(constraint); } /** * Does not include NOT NULL constraints, since they are stored * with the {@link Column} rather than separately. */ public boolean hasConstraints() { return !constraints.isEmpty(); } public Columns columns() { return columns; } public void addIndex(String name, ColumnNames indexColumns) { indexes.add(new Index(name, indexColumns)); } }