Search in sources :

Example 11 with Association

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

the class SqlQueryBuilder method addTypeToColumn.

private String addTypeToColumn(PersistentProperty prop, String column, boolean required) {
    if (prop instanceof Association) {
        throw new IllegalStateException("Association is not supported here");
    }
    AnnotationMetadata annotationMetadata = prop.getAnnotationMetadata();
    String definition = annotationMetadata.stringValue(MappedProperty.class, "definition").orElse(null);
    DataType dataType = prop.getDataType();
    if (definition != null) {
        return column + " " + definition;
    }
    OptionalInt precision = annotationMetadata.intValue("javax.persistence.Column", "precision");
    OptionalInt scale = annotationMetadata.intValue("javax.persistence.Column", "scale");
    switch(dataType) {
        case STRING:
            int stringLength = annotationMetadata.findAnnotation("javax.validation.constraints.Size$List").flatMap(v -> {
                Optional value = v.getValue(AnnotationValue.class);
                return (Optional<AnnotationValue<Annotation>>) value;
            }).map(v -> v.intValue("max")).orElseGet(() -> annotationMetadata.intValue("javax.persistence.Column", "length")).orElse(255);
            column += " VARCHAR(" + stringLength + ")";
            if (required) {
                column += " NOT NULL";
            }
            break;
        case UUID:
            if (dialect == Dialect.ORACLE || dialect == Dialect.MYSQL) {
                column += " VARCHAR(36)";
            } else if (dialect == Dialect.SQL_SERVER) {
                column += " UNIQUEIDENTIFIER";
            } else {
                column += " UUID";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case BOOLEAN:
            if (dialect == Dialect.ORACLE) {
                column += " NUMBER(3)";
            } else if (dialect == Dialect.SQL_SERVER) {
                column += " BIT NOT NULL";
            } else {
                column += " BOOLEAN";
                if (required) {
                    column += " NOT NULL";
                }
            }
            break;
        case TIMESTAMP:
            if (dialect == Dialect.ORACLE) {
                column += " TIMESTAMP";
                if (required) {
                    column += " NOT NULL";
                }
            } else if (dialect == Dialect.SQL_SERVER) {
                // sql server timestamp is an internal type, use datetime instead
                column += " DATETIME2";
                if (required) {
                    column += " NOT NULL";
                }
            } else if (dialect == Dialect.MYSQL) {
                // mysql doesn't allow timestamp without default
                column += " TIMESTAMP(6) DEFAULT NOW(6)";
            } else {
                column += " TIMESTAMP";
                if (required) {
                    column += " NOT NULL";
                }
            }
            break;
        case DATE:
            column += " DATE";
            if (required) {
                column += " NOT NULL";
            }
            break;
        case LONG:
            if (dialect == Dialect.ORACLE) {
                column += " NUMBER(19)";
            } else {
                column += " BIGINT";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case CHARACTER:
            column += " CHAR(1)";
            if (required) {
                column += " NOT NULL";
            }
            break;
        case INTEGER:
            if (precision.isPresent()) {
                String numericName = dialect == Dialect.ORACLE ? "NUMBER" : "NUMERIC";
                column += " " + numericName + "(" + precision.getAsInt() + ")";
            } else if (dialect == Dialect.ORACLE) {
                column += " NUMBER(10)";
            } else if (dialect == Dialect.POSTGRES) {
                column += " INTEGER";
            } else {
                column += " INT";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case BIGDECIMAL:
            if (precision.isPresent()) {
                if (scale.isPresent()) {
                    String numericName = dialect == Dialect.ORACLE ? "NUMBER" : "NUMERIC";
                    column += " " + numericName + "(" + precision.getAsInt() + "," + scale.getAsInt() + ")";
                } else {
                    column += " FLOAT(" + precision.getAsInt() + ")";
                }
            } else if (dialect == Dialect.ORACLE) {
                column += " FLOAT(126)";
            } else {
                column += " DECIMAL";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case FLOAT:
            if (precision.isPresent()) {
                if (scale.isPresent()) {
                    String numericName = dialect == Dialect.ORACLE ? "NUMBER" : "NUMERIC";
                    column += " " + numericName + "(" + precision.getAsInt() + "," + scale.getAsInt() + ")";
                } else {
                    column += " FLOAT(" + precision.getAsInt() + ")";
                }
            } else if (dialect == Dialect.ORACLE || dialect == Dialect.SQL_SERVER) {
                column += " FLOAT(53)";
            } else if (dialect == Dialect.POSTGRES) {
                column += " REAL";
            } else {
                column += " FLOAT";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case BYTE_ARRAY:
            if (dialect == Dialect.POSTGRES) {
                column += " BYTEA";
            } else if (dialect == Dialect.SQL_SERVER) {
                column += " VARBINARY(MAX)";
            } else if (dialect == Dialect.ORACLE) {
                column += " BLOB";
            } else {
                column += " BLOB";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case DOUBLE:
            if (precision.isPresent()) {
                if (scale.isPresent()) {
                    String numericName = dialect == Dialect.ORACLE ? "NUMBER" : "NUMERIC";
                    column += " " + numericName + "(" + precision.getAsInt() + "," + scale.getAsInt() + ")";
                } else {
                    column += " FLOAT(" + precision.getAsInt() + ")";
                }
            } else if (dialect == Dialect.ORACLE) {
                column += " FLOAT(23)";
            } else if (dialect == Dialect.MYSQL || dialect == Dialect.H2) {
                column += " DOUBLE";
            } else {
                column += " DOUBLE PRECISION";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case SHORT:
        case BYTE:
            if (dialect == Dialect.ORACLE) {
                column += " NUMBER(5)";
            } else if (dialect == Dialect.POSTGRES) {
                column += " SMALLINT";
            } else {
                column += " TINYINT";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case JSON:
            switch(dialect) {
                case POSTGRES:
                    column += " JSONB";
                    break;
                case SQL_SERVER:
                    column += " NVARCHAR(MAX)";
                    break;
                case ORACLE:
                    column += " CLOB";
                    break;
                default:
                    column += " JSON";
                    break;
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case STRING_ARRAY:
        case CHARACTER_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else {
                column += " VARCHAR(255) ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case SHORT_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else if (dialect == Dialect.POSTGRES) {
                column += " SMALLINT ARRAY";
            } else {
                column += " TINYINT ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case INTEGER_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else if (dialect == Dialect.POSTGRES) {
                column += " INTEGER ARRAY";
            } else {
                column += " INT ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case LONG_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else {
                column += " BIGINT ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case FLOAT_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else if (dialect == Dialect.POSTGRES) {
                column += " REAL ARRAY";
            } else {
                column += " FLOAT ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case DOUBLE_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else if (dialect == Dialect.POSTGRES) {
                column += " DOUBLE PRECISION ARRAY";
            } else {
                column += " DOUBLE ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        case BOOLEAN_ARRAY:
            if (dialect == Dialect.H2) {
                column += " ARRAY";
            } else {
                column += " BOOLEAN ARRAY";
            }
            if (required) {
                column += " NOT NULL";
            }
            break;
        default:
            if (prop.isEnum()) {
                column += " VARCHAR(255)";
                if (required) {
                    column += " NOT NULL";
                }
                break;
            } else if (prop.isAssignable(Clob.class)) {
                if (dialect == Dialect.POSTGRES) {
                    column += " TEXT";
                } else {
                    column += " CLOB";
                }
                if (required) {
                    column += " NOT NULL";
                }
                break;
            } else if (prop.isAssignable(Blob.class)) {
                if (dialect == Dialect.POSTGRES) {
                    column += " BYTEA";
                } else {
                    column += " BLOB";
                }
                if (required) {
                    column += " NOT NULL";
                }
                break;
            } else {
                throw new MappingException("Unable to create table column for property [" + prop.getName() + "] of entity [" + prop.getOwner().getName() + "] with unknown data type: " + dataType);
            }
    }
    return column;
}
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) Optional(java.util.Optional) OptionalInt(java.util.OptionalInt) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) MappingException(io.micronaut.data.exceptions.MappingException) Association(io.micronaut.data.model.Association) MappedProperty(io.micronaut.data.annotation.MappedProperty) DataType(io.micronaut.data.model.DataType) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Clob(java.sql.Clob)

Example 12 with Association

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

the class SqlQueryBuilder method buildJoin.

private void buildJoin(String joinType, StringBuilder sb, QueryState queryState, List<Association> joinAssociationsPath, String joinAlias, Association association, PersistentEntity associatedEntity, PersistentEntity associationOwner, String currentJoinAlias) {
    final boolean escape = shouldEscape(associationOwner);
    String mappedBy = association.getAnnotationMetadata().stringValue(Relation.class, "mappedBy").orElse(null);
    if (association.getKind() == Relation.Kind.MANY_TO_MANY || association.isForeignKey() && StringUtils.isEmpty(mappedBy)) {
        PersistentProperty identity = associatedEntity.getIdentity();
        if (identity == null) {
            throw new IllegalArgumentException("Associated entity [" + associatedEntity.getName() + "] defines no ID. Cannot join.");
        }
        final PersistentProperty associatedId = associationOwner.getIdentity();
        if (associatedId == null) {
            throw new MappingException("Cannot join on entity [" + associationOwner.getName() + "] that has no declared ID");
        }
        Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
        Association owningAssociation = inverseSide.orElse(association);
        boolean isAssociationOwner = !association.getInverseSide().isPresent();
        NamingStrategy namingStrategy = associationOwner.getNamingStrategy();
        AnnotationMetadata annotationMetadata = owningAssociation.getAnnotationMetadata();
        List<String> ownerJoinColumns = resolveJoinTableAssociatedColumns(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
        List<String> ownerJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
        List<String> associationJoinColumns = resolveJoinTableAssociatedColumns(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
        List<String> associationJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
        if (escape) {
            ownerJoinColumns = ownerJoinColumns.stream().map(this::quote).collect(Collectors.toList());
            ownerJoinTableColumns = ownerJoinTableColumns.stream().map(this::quote).collect(Collectors.toList());
            associationJoinColumns = associationJoinColumns.stream().map(this::quote).collect(Collectors.toList());
            associationJoinTableColumns = associationJoinTableColumns.stream().map(this::quote).collect(Collectors.toList());
        }
        String joinTableName = annotationMetadata.stringValue(ANN_JOIN_TABLE, "name").orElseGet(() -> namingStrategy.mappedName(association));
        String joinTableAlias = annotationMetadata.stringValue(ANN_JOIN_TABLE, "alias").orElseGet(() -> currentJoinAlias + joinTableName + "_");
        join(sb, queryState.getQueryModel(), joinType, escape ? quote(joinTableName) : joinTableName, joinTableAlias, joinAlias, ownerJoinColumns, ownerJoinTableColumns);
        sb.append(SPACE);
        join(sb, queryState.getQueryModel(), joinType, getTableName(associatedEntity), currentJoinAlias, joinTableAlias, associationJoinTableColumns, associationJoinColumns);
    } else {
        if (StringUtils.isNotEmpty(mappedBy)) {
            PersistentProperty ownerIdentity = associationOwner.getIdentity();
            if (ownerIdentity == null) {
                throw new IllegalArgumentException("Associated entity [" + associationOwner + "] defines no ID. Cannot join.");
            }
            PersistentPropertyPath mappedByPropertyPath = associatedEntity.getPropertyPath(mappedBy);
            if (mappedByPropertyPath == null) {
                throw new MappingException("Foreign key association with mappedBy references a property that doesn't exist [" + mappedBy + "] of entity: " + associatedEntity.getName());
            }
            join(sb, joinType, queryState, associatedEntity, associationOwner, joinAlias, currentJoinAlias, joinAssociationsPath, ownerIdentity, mappedByPropertyPath.getAssociations(), mappedByPropertyPath.getProperty());
        } else {
            PersistentProperty associatedProperty = association.getAssociatedEntity().getIdentity();
            if (associatedProperty == null) {
                throw new IllegalArgumentException("Associated entity [" + association.getAssociatedEntity().getName() + "] defines no ID. Cannot join.");
            }
            join(sb, joinType, queryState, associatedEntity, associationOwner, joinAlias, currentJoinAlias, joinAssociationsPath, association, Collections.emptyList(), associatedProperty);
        }
    }
}
Also used : NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Relation(io.micronaut.data.annotation.Relation) Association(io.micronaut.data.model.Association) PersistentProperty(io.micronaut.data.model.PersistentProperty) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) MappingException(io.micronaut.data.exceptions.MappingException)

Example 13 with Association

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

the class AbstractMongoCollectionsCreator method initialize.

/**
 * Initialize the collections.
 *
 * @param runtimeEntityRegistry      The entity registry
 * @param mongoConfigurations        The configuration
 * @param databaseOperationsProvider The database provider
 */
protected void initialize(RuntimeEntityRegistry runtimeEntityRegistry, List<AbstractMongoConfiguration> mongoConfigurations, DatabaseOperationsProvider<Dtbs> databaseOperationsProvider) {
    for (AbstractMongoConfiguration mongoConfiguration : mongoConfigurations) {
        // TODO: different initializer per conf
        Collection<BeanIntrospection<Object>> introspections = BeanIntrospector.SHARED.findIntrospections(MappedEntity.class);
        PersistentEntity[] entities = introspections.stream().filter(i -> !i.getBeanType().getName().contains("$")).filter(i -> !java.lang.reflect.Modifier.isAbstract(i.getBeanType().getModifiers())).map(e -> runtimeEntityRegistry.getEntity(e.getBeanType())).toArray(PersistentEntity[]::new);
        DatabaseOperations<Dtbs> databaseOperations = databaseOperationsProvider.get(mongoConfiguration);
        for (PersistentEntity entity : entities) {
            Dtbs database = databaseOperations.find(entity);
            Set<String> collections = databaseOperations.listCollectionNames(database);
            String persistedName = entity.getPersistedName();
            if (collections.add(persistedName)) {
                if (LOG.isInfoEnabled()) {
                    LOG.info("Creating collection: {} in database: {}", persistedName, databaseOperations.getDatabaseName(database));
                }
                databaseOperations.createCollection(database, persistedName);
            }
            for (PersistentProperty persistentProperty : entity.getPersistentProperties()) {
                if (persistentProperty instanceof Association) {
                    Association association = (Association) persistentProperty;
                    Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
                    if (association.getKind() == Relation.Kind.MANY_TO_MANY || association.isForeignKey() && !inverseSide.isPresent()) {
                        Association owningAssociation = inverseSide.orElse(association);
                        NamingStrategy namingStrategy = association.getOwner().getNamingStrategy();
                        String joinCollectionName = namingStrategy.mappedName(owningAssociation);
                        if (collections.add(joinCollectionName)) {
                            if (LOG.isInfoEnabled()) {
                                LOG.info("Creating collection: {} in database: {}", persistedName, databaseOperations.getDatabaseName(database));
                            }
                            databaseOperations.createCollection(database, joinCollectionName);
                        }
                    }
                }
            }
        }
    }
}
Also used : PersistentProperty(io.micronaut.data.model.PersistentProperty) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Logger(org.slf4j.Logger) Context(io.micronaut.context.annotation.Context) Qualifier(io.micronaut.context.Qualifier) Collection(java.util.Collection) LoggerFactory(org.slf4j.LoggerFactory) MappedEntity(io.micronaut.data.annotation.MappedEntity) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) Set(java.util.Set) RuntimeEntityRegistry(io.micronaut.data.model.runtime.RuntimeEntityRegistry) Internal(io.micronaut.core.annotation.Internal) Function(java.util.function.Function) List(java.util.List) Association(io.micronaut.data.model.Association) AbstractMongoConfiguration(io.micronaut.configuration.mongo.core.AbstractMongoConfiguration) NamedMongoConfiguration(io.micronaut.configuration.mongo.core.NamedMongoConfiguration) PersistentEntity(io.micronaut.data.model.PersistentEntity) BeanIntrospection(io.micronaut.core.beans.BeanIntrospection) Optional(java.util.Optional) BeanLocator(io.micronaut.context.BeanLocator) BeanIntrospector(io.micronaut.core.beans.BeanIntrospector) DefaultMongoConfiguration(io.micronaut.configuration.mongo.core.DefaultMongoConfiguration) Relation(io.micronaut.data.annotation.Relation) PersistentEntity(io.micronaut.data.model.PersistentEntity) PersistentProperty(io.micronaut.data.model.PersistentProperty) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Association(io.micronaut.data.model.Association) BeanIntrospection(io.micronaut.core.beans.BeanIntrospection) AbstractMongoConfiguration(io.micronaut.configuration.mongo.core.AbstractMongoConfiguration)

Example 14 with Association

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

the class AbstractSqlLikeQueryBuilder method traversePersistentProperties.

private void traversePersistentProperties(List<Association> associations, PersistentProperty property, BiConsumer<List<Association>, PersistentProperty> consumerProperty) {
    if (property instanceof Embedded) {
        Embedded embedded = (Embedded) property;
        PersistentEntity embeddedEntity = embedded.getAssociatedEntity();
        Collection<? extends PersistentProperty> embeddedProperties = embeddedEntity.getPersistentProperties();
        List<Association> newAssociations = new ArrayList<>(associations);
        newAssociations.add((Association) property);
        for (PersistentProperty embeddedProperty : embeddedProperties) {
            traversePersistentProperties(newAssociations, embeddedProperty, consumerProperty);
        }
    } else if (property instanceof Association) {
        Association association = (Association) property;
        if (association.isForeignKey()) {
            return;
        }
        List<Association> newAssociations = new ArrayList<>(associations);
        newAssociations.add((Association) property);
        PersistentEntity associatedEntity = association.getAssociatedEntity();
        PersistentProperty assocIdentity = associatedEntity.getIdentity();
        if (assocIdentity == null) {
            throw new IllegalStateException("Identity cannot be missing for: " + associatedEntity);
        }
        if (assocIdentity instanceof Association) {
            traversePersistentProperties(newAssociations, assocIdentity, consumerProperty);
        } else {
            consumerProperty.accept(newAssociations, assocIdentity);
        }
    } else {
        consumerProperty.accept(associations, property);
    }
}
Also used : Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Embedded(io.micronaut.data.model.Embedded) PersistentProperty(io.micronaut.data.model.PersistentProperty)

Example 15 with Association

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

the class AbstractSqlLikeQueryBuilder method buildSelect.

private void buildSelect(QueryState queryState, StringBuilder queryString, List<QueryModel.Projection> projectionList, String tableAlias, PersistentEntity entity) {
    if (projectionList.isEmpty()) {
        selectAllColumns(queryState, queryString);
    } else {
        for (Iterator i = projectionList.iterator(); i.hasNext(); ) {
            QueryModel.Projection projection = (QueryModel.Projection) i.next();
            if (projection instanceof QueryModel.LiteralProjection) {
                queryString.append(asLiteral(((QueryModel.LiteralProjection) projection).getValue()));
            } else if (projection instanceof QueryModel.CountProjection) {
                appendProjectionRowCount(queryString, tableAlias);
            } else if (projection instanceof QueryModel.DistinctProjection) {
                queryString.append("DISTINCT(").append(tableAlias).append(CLOSE_BRACKET);
            } else if (projection instanceof QueryModel.IdProjection) {
                if (entity.hasCompositeIdentity()) {
                    for (PersistentProperty identity : entity.getCompositeIdentity()) {
                        appendPropertyProjection(queryString, asQueryPropertyPath(queryState.getRootAlias(), identity));
                        queryString.append(COMMA);
                    }
                    queryString.setLength(queryString.length() - 1);
                } else if (entity.hasIdentity()) {
                    PersistentProperty identity = entity.getIdentity();
                    if (identity == null) {
                        throw new IllegalArgumentException("Cannot query on ID with entity that has no ID");
                    }
                    appendPropertyProjection(queryString, asQueryPropertyPath(queryState.getRootAlias(), identity));
                } else {
                    throw new IllegalArgumentException("Cannot query on ID with entity that has no ID");
                }
            } else if (projection instanceof QueryModel.PropertyProjection) {
                QueryModel.PropertyProjection pp = (QueryModel.PropertyProjection) projection;
                String alias = pp.getAlias().orElse(null);
                if (projection instanceof QueryModel.AvgProjection) {
                    appendFunctionProjection(queryState.getEntity(), AVG, pp, tableAlias, queryString);
                } else if (projection instanceof QueryModel.DistinctPropertyProjection) {
                    appendFunctionProjection(queryState.getEntity(), DISTINCT, pp, tableAlias, queryString);
                } else if (projection instanceof QueryModel.SumProjection) {
                    appendFunctionProjection(queryState.getEntity(), SUM, pp, tableAlias, queryString);
                } else if (projection instanceof QueryModel.MinProjection) {
                    appendFunctionProjection(queryState.getEntity(), MIN, pp, tableAlias, queryString);
                } else if (projection instanceof QueryModel.MaxProjection) {
                    appendFunctionProjection(queryState.getEntity(), MAX, pp, tableAlias, queryString);
                } else if (projection instanceof QueryModel.CountDistinctProjection) {
                    appendFunctionProjection(queryState.getEntity(), COUNT_DISTINCT, pp, tableAlias, queryString);
                    queryString.append(CLOSE_BRACKET);
                } else {
                    String propertyName = pp.getPropertyName();
                    PersistentPropertyPath propertyPath = entity.getPropertyPath(propertyName);
                    if (propertyPath == null) {
                        throw new IllegalArgumentException("Cannot project on non-existent property: " + propertyName);
                    }
                    PersistentProperty property = propertyPath.getProperty();
                    if (property instanceof Association && !(property instanceof Embedded)) {
                        if (!queryState.isJoined(propertyPath.getPath())) {
                            queryString.setLength(queryString.length() - 1);
                            continue;
                        }
                        String joinAlias = queryState.computeAlias(propertyPath.getPath());
                        selectAllColumns(((Association) property).getAssociatedEntity(), joinAlias, queryString);
                    } else {
                        appendPropertyProjection(queryString, findProperty(queryState, propertyName, null));
                    }
                }
                if (alias != null) {
                    queryString.append(AS_CLAUSE).append(alias);
                }
            }
            if (i.hasNext()) {
                queryString.append(COMMA);
            }
        }
    }
}
Also used : PersistentProperty(io.micronaut.data.model.PersistentProperty) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) QueryModel(io.micronaut.data.model.query.QueryModel) Association(io.micronaut.data.model.Association) Iterator(java.util.Iterator) Embedded(io.micronaut.data.model.Embedded)

Aggregations

Association (io.micronaut.data.model.Association)46 PersistentProperty (io.micronaut.data.model.PersistentProperty)21 ArrayList (java.util.ArrayList)21 Embedded (io.micronaut.data.model.Embedded)17 StringJoiner (java.util.StringJoiner)16 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)15 NonNull (io.micronaut.core.annotation.NonNull)14 PersistentEntity (io.micronaut.data.model.PersistentEntity)14 List (java.util.List)14 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)13 Relation (io.micronaut.data.annotation.Relation)11 NamingStrategy (io.micronaut.data.model.naming.NamingStrategy)11 JoinPath (io.micronaut.data.model.query.JoinPath)11 Map (java.util.Map)11 HashMap (java.util.HashMap)10 Optional (java.util.Optional)10 Collectors (java.util.stream.Collectors)10 MappedEntity (io.micronaut.data.annotation.MappedEntity)9 QueryModel (io.micronaut.data.model.query.QueryModel)9 Collections (java.util.Collections)9