Search in sources :

Example 26 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class SqlQueryBuilder method buildCreateTableStatements.

/**
 * Builds the create table statement. Designed for testing and not production usage. For production a
 * SQL migration tool such as Flyway or Liquibase is recommended.
 *
 * @param entity The entity
 * @return The tables for the give entity
 */
@Experimental
@NonNull
public String[] buildCreateTableStatements(@NonNull PersistentEntity entity) {
    ArgumentUtils.requireNonNull("entity", entity);
    final String unescapedTableName = getUnescapedTableName(entity);
    String tableName = getTableName(entity);
    boolean escape = shouldEscape(entity);
    PersistentProperty identity = entity.getIdentity();
    List<String> createStatements = new ArrayList<>();
    String schema = entity.getAnnotationMetadata().stringValue(MappedEntity.class, SqlMembers.SCHEMA).orElse(null);
    if (StringUtils.isNotEmpty(schema)) {
        if (escape) {
            schema = quote(schema);
        }
        createStatements.add("CREATE SCHEMA " + schema + ";");
    }
    Collection<Association> foreignKeyAssociations = getJoinTableAssociations(entity);
    NamingStrategy namingStrategy = entity.getNamingStrategy();
    if (CollectionUtils.isNotEmpty(foreignKeyAssociations)) {
        for (Association association : foreignKeyAssociations) {
            StringBuilder joinTableBuilder = new StringBuilder("CREATE TABLE ");
            PersistentEntity associatedEntity = association.getAssociatedEntity();
            Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
            Association owningAssociation = inverseSide.orElse(association);
            AnnotationMetadata annotationMetadata = owningAssociation.getAnnotationMetadata();
            String joinTableName = annotationMetadata.stringValue(ANN_JOIN_TABLE, "name").orElseGet(() -> namingStrategy.mappedName(association));
            if (escape) {
                joinTableName = quote(joinTableName);
            }
            joinTableBuilder.append(joinTableName).append(" (");
            List<PersistentPropertyPath> leftProperties = new ArrayList<>();
            List<PersistentPropertyPath> rightProperties = new ArrayList<>();
            boolean isAssociationOwner = !inverseSide.isPresent();
            List<String> leftJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, isAssociationOwner, entity, namingStrategy);
            List<String> rightJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, !isAssociationOwner, association.getAssociatedEntity(), namingStrategy);
            traversePersistentProperties(entity.getIdentity(), (associations, property) -> {
                leftProperties.add(PersistentPropertyPath.of(associations, property, ""));
            });
            traversePersistentProperties(associatedEntity.getIdentity(), (associations, property) -> {
                rightProperties.add(PersistentPropertyPath.of(associations, property, ""));
            });
            if (leftJoinTableColumns.size() == leftProperties.size()) {
                for (int i = 0; i < leftJoinTableColumns.size(); i++) {
                    PersistentPropertyPath pp = leftProperties.get(i);
                    String columnName = leftJoinTableColumns.get(i);
                    if (escape) {
                        columnName = quote(columnName);
                    }
                    joinTableBuilder.append(addTypeToColumn(pp.getProperty(), columnName, true)).append(',');
                }
            } else {
                for (PersistentPropertyPath pp : leftProperties) {
                    String columnName = namingStrategy.mappedJoinTableColumn(entity, pp.getAssociations(), pp.getProperty());
                    if (escape) {
                        columnName = quote(columnName);
                    }
                    joinTableBuilder.append(addTypeToColumn(pp.getProperty(), columnName, true)).append(',');
                }
            }
            if (rightJoinTableColumns.size() == rightProperties.size()) {
                for (int i = 0; i < rightJoinTableColumns.size(); i++) {
                    PersistentPropertyPath pp = rightProperties.get(i);
                    String columnName = rightJoinTableColumns.get(i);
                    if (escape) {
                        columnName = quote(columnName);
                    }
                    joinTableBuilder.append(addTypeToColumn(pp.getProperty(), columnName, true)).append(',');
                }
            } else {
                for (PersistentPropertyPath pp : rightProperties) {
                    String columnName = namingStrategy.mappedJoinTableColumn(entity, pp.getAssociations(), pp.getProperty());
                    if (escape) {
                        columnName = quote(columnName);
                    }
                    joinTableBuilder.append(addTypeToColumn(pp.getProperty(), columnName, true)).append(',');
                }
            }
            joinTableBuilder.setLength(joinTableBuilder.length() - 1);
            joinTableBuilder.append(")");
            if (dialect != Dialect.ORACLE) {
                joinTableBuilder.append(';');
            }
            createStatements.add(joinTableBuilder.toString());
        }
    }
    boolean generatePkAfterColumns = false;
    List<String> primaryColumnsName = new ArrayList<>();
    List<String> columns = new ArrayList<>();
    if (identity != null) {
        List<PersistentPropertyPath> ids = new ArrayList<>();
        traversePersistentProperties(identity, (associations, property) -> {
            ids.add(PersistentPropertyPath.of(associations, property, ""));
        });
        if (ids.size() > 1) {
            generatePkAfterColumns = true;
        }
        boolean finalGeneratePkAfterColumns = generatePkAfterColumns;
        for (PersistentPropertyPath pp : ids) {
            String column = namingStrategy.mappedName(pp.getAssociations(), pp.getProperty());
            if (escape) {
                column = quote(column);
            }
            primaryColumnsName.add(column);
            column = addTypeToColumn(pp.getProperty(), column, isRequired(pp.getAssociations(), pp.getProperty()));
            if (isNotForeign(pp.getAssociations())) {
                column = addGeneratedStatementToColumn(pp.getProperty(), column, !finalGeneratePkAfterColumns);
            }
            columns.add(column);
        }
    }
    PersistentProperty version = entity.getVersion();
    if (version != null) {
        String column = namingStrategy.mappedName(Collections.emptyList(), version);
        if (escape) {
            column = quote(column);
        }
        column = addTypeToColumn(version, column, true);
        columns.add(column);
    }
    BiConsumer<List<Association>, PersistentProperty> addColumn = (associations, property) -> {
        String column = namingStrategy.mappedName(associations, property);
        if (escape) {
            column = quote(column);
        }
        column = addTypeToColumn(property, column, isRequired(associations, property));
        if (isNotForeign(associations)) {
            column = addGeneratedStatementToColumn(property, column, false);
        }
        columns.add(column);
    };
    for (PersistentProperty prop : entity.getPersistentProperties()) {
        traversePersistentProperties(prop, addColumn);
    }
    StringBuilder builder = new StringBuilder("CREATE TABLE ").append(tableName).append(" (");
    builder.append(String.join(",", columns));
    if (generatePkAfterColumns) {
        builder.append(", PRIMARY KEY(").append(String.join(",", primaryColumnsName)).append(')');
    }
    if (dialect == Dialect.ORACLE) {
        builder.append(")");
    } else {
        builder.append(");");
    }
    if (identity != null && identity.isGenerated()) {
        GeneratedValue.Type idGeneratorType = identity.getAnnotationMetadata().enumValue(GeneratedValue.class, GeneratedValue.Type.class).orElseGet(() -> selectAutoStrategy(identity));
        boolean isSequence = idGeneratorType == GeneratedValue.Type.SEQUENCE;
        final String generatedDefinition = identity.getAnnotationMetadata().stringValue(GeneratedValue.class, "definition").orElse(null);
        if (generatedDefinition != null) {
            createStatements.add(generatedDefinition);
        } else if (isSequence) {
            final boolean isSqlServer = dialect == Dialect.SQL_SERVER;
            final String sequenceName = quote(unescapedTableName + SEQ_SUFFIX);
            String createSequenceStmt = "CREATE SEQUENCE " + sequenceName;
            if (isSqlServer) {
                createSequenceStmt += " AS BIGINT";
            }
            createSequenceStmt += " MINVALUE 1 START WITH 1";
            if (dialect == Dialect.ORACLE) {
                createSequenceStmt += " NOCACHE NOCYCLE";
            } else {
                if (isSqlServer) {
                    createSequenceStmt += " INCREMENT BY 1";
                }
            }
            createStatements.add(createSequenceStmt);
        }
    }
    createStatements.add(builder.toString());
    addIndexes(entity, tableName, createStatements);
    return createStatements.toArray(new String[0]);
}
Also used : DataType(io.micronaut.data.model.DataType) SqlMembers(io.micronaut.data.annotation.sql.SqlMembers) Arrays(java.util.Arrays) IDENTITY(io.micronaut.data.annotation.GeneratedValue.Type.IDENTITY) ListIterator(java.util.ListIterator) ArrayUtils(io.micronaut.core.util.ArrayUtils) SEQUENCE(io.micronaut.data.annotation.GeneratedValue.Type.SEQUENCE) MappedProperty(io.micronaut.data.annotation.MappedProperty) GeneratedValue(io.micronaut.data.annotation.GeneratedValue) Locale(java.util.Locale) Map(java.util.Map) QueryResult(io.micronaut.data.model.query.builder.QueryResult) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) PersistentProperty(io.micronaut.data.model.PersistentProperty) Index(io.micronaut.data.annotation.Index) MappingException(io.micronaut.data.exceptions.MappingException) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) AUTO(io.micronaut.data.annotation.GeneratedValue.Type.AUTO) StringUtils(io.micronaut.core.util.StringUtils) AbstractSqlLikeQueryBuilder(io.micronaut.data.model.query.builder.AbstractSqlLikeQueryBuilder) List(java.util.List) Stream(java.util.stream.Stream) UUID(io.micronaut.data.annotation.GeneratedValue.Type.UUID) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) Experimental(io.micronaut.core.annotation.Experimental) Pattern(java.util.regex.Pattern) Relation(io.micronaut.data.annotation.Relation) IntStream(java.util.stream.IntStream) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) Join(io.micronaut.data.annotation.Join) Creator(io.micronaut.core.annotation.Creator) QueryModel(io.micronaut.data.model.query.QueryModel) MappedEntity(io.micronaut.data.annotation.MappedEntity) HashMap(java.util.HashMap) OptionalInt(java.util.OptionalInt) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Embedded(io.micronaut.data.model.Embedded) Pageable(io.micronaut.data.model.Pageable) BiConsumer(java.util.function.BiConsumer) Clob(java.sql.Clob) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Indexes(io.micronaut.data.annotation.Indexes) NonNull(io.micronaut.core.annotation.NonNull) JoinPath(io.micronaut.data.model.query.JoinPath) Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity) CollectionUtils(io.micronaut.core.util.CollectionUtils) StringJoiner(java.util.StringJoiner) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) Repository(io.micronaut.data.annotation.Repository) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Blob(java.sql.Blob) Collections(java.util.Collections) MappedEntity(io.micronaut.data.annotation.MappedEntity) PersistentEntity(io.micronaut.data.model.PersistentEntity) ArrayList(java.util.ArrayList) PersistentProperty(io.micronaut.data.model.PersistentProperty) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) GeneratedValue(io.micronaut.data.annotation.GeneratedValue) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) DataType(io.micronaut.data.model.DataType) Association(io.micronaut.data.model.Association) List(java.util.List) ArrayList(java.util.ArrayList) Experimental(io.micronaut.core.annotation.Experimental) NonNull(io.micronaut.core.annotation.NonNull)

Example 27 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class QueryModelPredicateVisitor method getPropertyToValueRestriction.

private QueryModel.Criterion getPropertyToValueRestriction(PredicateBinaryOp op, PersistentPropertyPath<?> left, Object right) {
    String leftProperty = getPropertyPath(left);
    Object rightProperty = asValue(right);
    switch(op) {
        case EQUALS:
            PersistentProperty property = left.getProperty();
            PersistentEntity owner = property.getOwner();
            if (left.getAssociations().isEmpty() && (owner.hasIdentity() && owner.getIdentity() == property)) {
                return Restrictions.idEq(rightProperty);
            } else if (left.getAssociations().isEmpty() && owner.getVersion() == property) {
                return Restrictions.versionEq(rightProperty);
            } else {
                return Restrictions.eq(leftProperty, rightProperty);
            }
        case NOT_EQUALS:
            return Restrictions.ne(leftProperty, rightProperty);
        case GREATER_THAN:
            return Restrictions.gt(leftProperty, rightProperty);
        case GREATER_THAN_OR_EQUALS:
            return Restrictions.gte(leftProperty, rightProperty);
        case LESS_THAN:
            return Restrictions.lt(leftProperty, rightProperty);
        case LESS_THAN_OR_EQUALS:
            return Restrictions.lte(leftProperty, rightProperty);
        case CONTAINS:
            return Restrictions.contains(leftProperty, rightProperty);
        case ENDS_WITH:
            return Restrictions.endsWith(leftProperty, rightProperty);
        case STARTS_WITH:
            return Restrictions.startsWith(leftProperty, rightProperty);
        case ILIKE:
            return Restrictions.ilike(leftProperty, rightProperty);
        case RLIKE:
            return Restrictions.rlike(leftProperty, rightProperty);
        case LIKE:
            return Restrictions.like(leftProperty, rightProperty);
        case REGEX:
            return Restrictions.regex(leftProperty, rightProperty);
        case EQUALS_IGNORE_CASE:
            return Restrictions.eq(leftProperty, rightProperty).ignoreCase(true);
        case NOT_EQUALS_IGNORE_CASE:
            return Restrictions.ne(leftProperty, rightProperty).ignoreCase(true);
        case STARTS_WITH_IGNORE_CASE:
            return Restrictions.startsWith(leftProperty, rightProperty).ignoreCase(true);
        case ENDS_WITH_IGNORE_CASE:
            return Restrictions.endsWith(leftProperty, rightProperty).ignoreCase(true);
        default:
            throw new IllegalStateException("Unsupported property to value operation: " + op);
    }
}
Also used : PersistentEntity(io.micronaut.data.model.PersistentEntity) PersistentProperty(io.micronaut.data.model.PersistentProperty)

Aggregations

PersistentEntity (io.micronaut.data.model.PersistentEntity)27 PersistentProperty (io.micronaut.data.model.PersistentProperty)15 Association (io.micronaut.data.model.Association)13 Embedded (io.micronaut.data.model.Embedded)11 List (java.util.List)11 ArrayList (java.util.ArrayList)10 Collection (java.util.Collection)9 CollectionUtils (io.micronaut.core.util.CollectionUtils)8 MappedEntity (io.micronaut.data.annotation.MappedEntity)8 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)7 NonNull (io.micronaut.core.annotation.NonNull)7 ArrayUtils (io.micronaut.core.util.ArrayUtils)7 Relation (io.micronaut.data.annotation.Relation)7 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)7 NamingStrategy (io.micronaut.data.model.naming.NamingStrategy)7 JoinPath (io.micronaut.data.model.query.JoinPath)7 ArgumentUtils (io.micronaut.core.util.ArgumentUtils)6 StringUtils (io.micronaut.core.util.StringUtils)6 MappingException (io.micronaut.data.exceptions.MappingException)6 Pageable (io.micronaut.data.model.Pageable)6