svnno****@sourc*****
svnno****@sourc*****
2009年 4月 8日 (水) 19:51:07 JST
Revision: 3188 http://svn.sourceforge.jp/view?root=jiemamy&view=rev&rev=3188 Author: daisuke_m Date: 2009-04-08 19:51:07 +0900 (Wed, 08 Apr 2009) Log Message: ----------- MySQLでのテストも通過。 Modified Paths: -------------- artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/utils/DatabaseCleaner.java artemis/trunk/jiemamy-dialect-mysql/src/main/java/org/jiemamy/dialect/mysql/MySqlEmitter.java -------------- next part -------------- Modified: artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/utils/DatabaseCleaner.java =================================================================== --- artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/utils/DatabaseCleaner.java 2009-04-08 10:39:47 UTC (rev 3187) +++ artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/utils/DatabaseCleaner.java 2009-04-08 10:51:07 UTC (rev 3188) @@ -80,7 +80,7 @@ for (EntityModel entityModel : sortedEntityList) { String type = entityModel instanceof TableModel ? "TABLE" : "VIEW"; - sqlExecuter.execute(String.format("DROP %s \"%s\";", type, entityModel.getName())); + sqlExecuter.execute(String.format("DROP %s %s;", type, entityModel.getName())); } } catch (DriverNotFoundException e) { throw new ImportException(e); Modified: artemis/trunk/jiemamy-dialect-mysql/src/main/java/org/jiemamy/dialect/mysql/MySqlEmitter.java =================================================================== --- artemis/trunk/jiemamy-dialect-mysql/src/main/java/org/jiemamy/dialect/mysql/MySqlEmitter.java 2009-04-08 10:39:47 UTC (rev 3187) +++ artemis/trunk/jiemamy-dialect-mysql/src/main/java/org/jiemamy/dialect/mysql/MySqlEmitter.java 2009-04-08 10:51:07 UTC (rev 3188) @@ -21,6 +21,9 @@ import java.util.Arrays; import java.util.List; +import org.apache.commons.lang.StringUtils; + +import org.jiemamy.ReferenceResolver; import org.jiemamy.dialect.DataTypeResolver; import org.jiemamy.dialect.internal.SqlEmitter; import org.jiemamy.dialect.internal.TokenResolver; @@ -35,6 +38,15 @@ import org.jiemamy.internal.model.sql.SqlStatementImpl; import org.jiemamy.model.attribute.AttributeModel; import org.jiemamy.model.attribute.ColumnModel; +import org.jiemamy.model.attribute.ColumnRef; +import org.jiemamy.model.attribute.constraint.CheckConstraint; +import org.jiemamy.model.attribute.constraint.ColumnCheckConstraint; +import org.jiemamy.model.attribute.constraint.ConstraintModel; +import org.jiemamy.model.attribute.constraint.ForeignKey; +import org.jiemamy.model.attribute.constraint.NotNullConstraint; +import org.jiemamy.model.attribute.constraint.PrimaryKey; +import org.jiemamy.model.attribute.constraint.TableCheckConstraint; +import org.jiemamy.model.attribute.constraint.UniqueKey; import org.jiemamy.model.datatype.BuiltinDataType; import org.jiemamy.model.datatype.DataType; import org.jiemamy.model.datatype.LiteralType; @@ -46,6 +58,8 @@ import org.jiemamy.model.sql.Token; import org.jiemamy.utils.CollectionsUtil; import org.jiemamy.utils.Disablable; +import org.jiemamy.utils.model.DataTypeUtil; +import org.jiemamy.utils.model.ForeignKeyUtil; /** * MySQL用の{@link SqlEmitter}実装クラス。 @@ -83,6 +97,232 @@ /** + * 属性の出力戦略列挙型。 + * + * @author daisuke + */ + protected enum MySqlAttributeEmitStrategy { + + /** カラムの出力戦略 */ + COLUMN(ColumnModel.class) { + + @Override + public List<Token> emit(AttributeModel attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver) { + ReferenceResolver referenceResolver = attributeModel.getJiemamy().getReferenceResolver(); + ColumnModel columnModel = (ColumnModel) attributeModel; + List<Token> tokens = CollectionsUtil.newArrayList(); + tokens.add(Identifier.of(columnModel.getName())); + tokens.addAll(dataTypeResolver.resolveDataType(columnModel.getDataType(), referenceResolver)); + + if (StringUtils.isEmpty(columnModel.getDefaultValue()) == false) { + BuiltinDataType builtinDataType = + DataTypeUtil.toBuiltinDataType(columnModel.getDataType(), referenceResolver); + tokens.add(Keyword.DEFAULT); + tokens.add(Literal + .of(columnModel.getDefaultValue(), builtinDataType.getCategory().getLiteralType())); + } + + NotNullConstraint nnModel = columnModel.getNotNullConstraint(); + if (nnModel != null) { + if (StringUtils.isEmpty(nnModel.getName()) == false) { + tokens.add(Keyword.CONSTRAINT); + tokens.add(Identifier.of(nnModel.getName())); + } + tokens.add(Keyword.NOT); + tokens.add(Keyword.NULL); + } + + UniqueKey uniqueKey = columnModel.getUniqueKey(); + if (uniqueKey != null) { + if (StringUtils.isEmpty(uniqueKey.getName()) == false) { + tokens.add(Keyword.CONSTRAINT); + tokens.add(Identifier.of(uniqueKey.getName())); + } + tokens.add(Keyword.UNIQUE); + } + + PrimaryKey primaryKey = columnModel.getPrimaryKey(); + if (primaryKey != null) { + tokens.add(Keyword.PRIMARY); + tokens.add(Keyword.KEY); + } + + ColumnCheckConstraint checkConstraint = columnModel.getCheckConstraint(); + if (checkConstraint != null) { + tokens.add(Keyword.CHECK); + tokens.add(Separator.LEFT_PAREN); + tokens.add(Literal.of(checkConstraint.getExpression(), LiteralType.FRAGMENT)); + tokens.add(Separator.RIGHT_PAREN); + } + + return tokens; + } + }, + + /** 主キーの出力戦略 */ + PK(PrimaryKey.class) { + + @Override + public List<Token> emit(AttributeModel attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver) { + PrimaryKey primaryKey = (PrimaryKey) attributeModel; + List<Token> tokens = CollectionsUtil.newArrayList(); + addConstraintNameDefinition(primaryKey, tokens); + tokens.add(Keyword.PRIMARY); + tokens.add(Keyword.KEY); + ReferenceResolver referenceResolver = attributeModel.getJiemamy().getReferenceResolver(); + addColumnList(tokens, primaryKey.getKeyColumns(), referenceResolver); + return tokens; + } + + }, + + /** ユニークキーの出力戦略 */ + UK(UniqueKey.class) { + + @Override + public List<Token> emit(AttributeModel attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver) { + UniqueKey uniqueKey = (UniqueKey) attributeModel; + List<Token> tokens = CollectionsUtil.newArrayList(); + addConstraintNameDefinition(uniqueKey, tokens); + tokens.add(Keyword.UNIQUE); + tokens.add(Keyword.KEY); + ReferenceResolver referenceResolver = attributeModel.getJiemamy().getReferenceResolver(); + addColumnList(tokens, uniqueKey.getKeyColumns(), referenceResolver); + return tokens; + } + }, + + /** 外部キーの出力戦略 */ + FK(ForeignKey.class) { + + @Override + public List<Token> emit(AttributeModel attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver) { + ReferenceResolver referenceResolver = attributeModel.getJiemamy().getReferenceResolver(); + ForeignKey foreignKey = (ForeignKey) attributeModel; + List<Token> tokens = CollectionsUtil.newArrayList(); + addConstraintNameDefinition(foreignKey, tokens); + tokens.add(Keyword.FOREIGN); + tokens.add(Keyword.KEY); + addColumnList(tokens, foreignKey.getKeyColumns(), referenceResolver); + tokens.add(Keyword.REFERENCES); + EntityModel referenceEntity = ForeignKeyUtil.getReferenceEntity(foreignKey); + tokens.add(Identifier.of(referenceEntity.getName())); + addColumnList(tokens, foreignKey.getReferenceColumns(), referenceResolver); + + if (foreignKey.getMatchType() != null) { + tokens.addAll(tokenResolver.resolve(foreignKey.getMatchType())); + } + if (foreignKey.getOnDelete() != null) { + tokens.add(Keyword.ON); + tokens.add(Keyword.DELETE); + tokens.addAll(tokenResolver.resolve(foreignKey.getOnDelete())); + } + if (foreignKey.getOnUpdate() != null) { + tokens.add(Keyword.ON); + tokens.add(Keyword.UPDATE); + tokens.addAll(tokenResolver.resolve(foreignKey.getOnUpdate())); + } + // TODO MySQLのDEFERRABLEについて、いちい君に確認の後、対策。 +// if (foreignKey.getDeferrability() != null) { +// Deferrability deferrability = foreignKey.getDeferrability(); +// if (deferrability.isDeferrable() == false) { +// tokens.add(Keyword.NOT); +// } +// tokens.add(Keyword.DEFERRABLE); +// if (deferrability.getInitiallyCheckTime() != null) { +// tokens.addAll(tokenResolver.resolve(deferrability.getInitiallyCheckTime())); +// } +// } + return tokens; + } + }, + + /** CHECK制約の出力戦略 */ + TABLE_CHECK(TableCheckConstraint.class) { + + @Override + public List<Token> emit(AttributeModel attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver) { + CheckConstraint checkConstraint = (CheckConstraint) attributeModel; + List<Token> tokens = CollectionsUtil.newArrayList(); + addConstraintNameDefinition(checkConstraint, tokens); + tokens.add(Keyword.CHECK); + tokens.add(Separator.LEFT_PAREN); + tokens.add(Literal.of(checkConstraint.getExpression(), LiteralType.FRAGMENT)); + tokens.add(Separator.RIGHT_PAREN); + return tokens; + } + }; + + /** + * 属性モデルから出力戦略を取得する。 + * + * @param attribute 出力対象の属性モデル + * @return 出力戦略 + */ + public static MySqlAttributeEmitStrategy fromAttribute(AttributeModel attribute) { + for (MySqlAttributeEmitStrategy s : values()) { + if (s.clazz == attribute.getClass()) { + return s; + } + for (Class<?> c : attribute.getClass().getInterfaces()) { + if (s.clazz == c) { + return s; + } + } + } + return null; + } + + private static void addColumnList(List<Token> tokens, List<ColumnRef> columnRefs, + ReferenceResolver referenceResolver) { + tokens.add(Separator.LEFT_PAREN); + for (ColumnRef columnRef : columnRefs) { + ColumnModel columnModel = referenceResolver.resolve(columnRef); + tokens.add(Identifier.of(columnModel.getName())); + tokens.add(Separator.COMMA); + } + + if (columnRefs.isEmpty() == false) { + tokens.remove(tokens.size() - 1); + } + tokens.add(Separator.RIGHT_PAREN); + } + + private static void addConstraintNameDefinition(ConstraintModel constraint, List<Token> tokens) { + if (StringUtils.isEmpty(constraint.getName()) == false) { + tokens.add(Keyword.CONSTRAINT); + tokens.add(Identifier.of(constraint.getName())); + } + } + + + private final Class<? extends AttributeModel> clazz; + + + MySqlAttributeEmitStrategy(Class<? extends AttributeModel> clazz) { + this.clazz = clazz; + } + + /** + * 属性モデルからトークンシーケンスを出力する。 + * + * @param attributeModel 属性モデル + * @param dataTypeResolver データ型リゾルバ + * @param tokenResolver トークンリゾルバ + * @param <T> 出力する属性モデルの型 + * @return トークンシーケンス + */ + public abstract <T extends AttributeModel>List<Token> emit(T attributeModel, DataTypeResolver dataTypeResolver, + TokenResolver tokenResolver); + + } + + /** * MySQL用エンティティ出力戦略。 * * @author daisuke @@ -107,7 +347,7 @@ continue; } - AttributeEmitStrategy strategy = AttributeEmitStrategy.fromAttribute(attributeModel); + MySqlAttributeEmitStrategy strategy = MySqlAttributeEmitStrategy.fromAttribute(attributeModel); List<Token> attributes = strategy.emit(attributeModel, dataTypeResolver, tokenResolver); tokens.addAll(attributes);