Search in sources :

Example 1 with QueryAttribute

use of io.requery.meta.QueryAttribute in project requery by requery.

the class DefaultOutput method appendConditionValue.

private void appendConditionValue(Expression expression, Object value, boolean parameterize) {
    if (value instanceof QueryAttribute) {
        appendColumn((Expression<?>) value);
    } else if (value instanceof Supplier && ((Supplier) value).get() instanceof QueryAttribute) {
        appendColumn((Expression<?>) ((Supplier) value).get());
    } else if (value instanceof NamedExpression) {
        NamedExpression namedExpression = (NamedExpression) value;
        qb.append(namedExpression.getName());
    } else if (value instanceof Function) {
        appendFunction((Function) value);
    } else if (value instanceof Collection && expression.getExpressionType() == ExpressionType.ROW) {
        qb.openParenthesis();
        qb.commaSeparated((Collection) value);
        qb.closeParenthesis();
    } else {
        if (parameterize) {
            if (parameters != null) {
                parameters.add(expression, value);
            }
            qb.append("?").space();
        } else {
            if (value instanceof CharSequence) {
                qb.appendQuoted(value.toString()).space();
            } else {
                qb.append(value).space();
            }
        }
    }
}
Also used : Function(io.requery.query.function.Function) Expression(io.requery.query.Expression) NamedExpression(io.requery.query.NamedExpression) RowExpression(io.requery.query.RowExpression) NamedExpression(io.requery.query.NamedExpression) QueryAttribute(io.requery.meta.QueryAttribute) Collection(java.util.Collection) Supplier(io.requery.util.function.Supplier)

Example 2 with QueryAttribute

use of io.requery.meta.QueryAttribute in project requery by requery.

the class EntityWriter method updateAssociation.

@SuppressWarnings("unchecked")
private void updateAssociation(Cascade mode, E entity, EntityProxy<E> proxy, Attribute<E, ?> attribute) {
    switch(attribute.getCardinality()) {
        case ONE_TO_ONE:
            S value = (S) proxy.get(attribute, false);
            if (value != null) {
                Attribute<S, Object> mapped = Attributes.get(attribute.getMappedAttribute());
                EntityProxy<S> referred = context.proxyOf(value, true);
                referred.set(mapped, entity, PropertyState.MODIFIED);
                cascadeWrite(mode, value, referred);
            } else if (!stateless) {
                throw new PersistenceException("1-1 relationship can only be removed from the owning side");
            }
            break;
        case ONE_TO_MANY:
            Object relation = proxy.get(attribute, false);
            if (relation instanceof ObservableCollection) {
                ObservableCollection<S> collection = (ObservableCollection<S>) relation;
                CollectionChanges<?, S> changes = (CollectionChanges<?, S>) collection.observer();
                List<S> added = new ArrayList<>(changes.addedElements());
                List<S> removed = new ArrayList<>(changes.removedElements());
                changes.clear();
                for (S element : added) {
                    updateMappedAssociation(mode, element, attribute, entity);
                }
                for (S element : removed) {
                    updateMappedAssociation(Cascade.UPDATE, element, attribute, null);
                }
            } else if (relation instanceof Iterable) {
                Iterable<S> iterable = (Iterable<S>) relation;
                for (S added : iterable) {
                    updateMappedAssociation(mode, added, attribute, entity);
                }
            } else {
                throw new IllegalStateException("unsupported relation type " + relation);
            }
            break;
        case MANY_TO_MANY:
            final Class referencedClass = attribute.getReferencedClass();
            if (referencedClass == null) {
                throw new IllegalStateException("Invalid referenced class in " + attribute);
            }
            Type<?> referencedType = model.typeOf(referencedClass);
            QueryAttribute<S, Object> tKey = null;
            QueryAttribute<S, Object> uKey = null;
            for (Attribute a : referencedType.getAttributes()) {
                Class<?> referenced = a.getReferencedClass();
                if (referenced != null) {
                    if (tKey == null && entityClass.isAssignableFrom(referenced)) {
                        tKey = Attributes.query(a);
                    } else if (attribute.getElementClass() != null && attribute.getElementClass().isAssignableFrom(referenced)) {
                        uKey = Attributes.query(a);
                    }
                }
            }
            Objects.requireNotNull(tKey);
            Objects.requireNotNull(uKey);
            Attribute<E, Object> tRef = Attributes.get(tKey.getReferencedAttribute());
            Attribute<S, Object> uRef = Attributes.get(uKey.getReferencedAttribute());
            CollectionChanges<?, S> changes = null;
            relation = proxy.get(attribute, false);
            Iterable<S> addedElements = (Iterable<S>) relation;
            boolean isObservable = relation instanceof ObservableCollection;
            if (relation instanceof ObservableCollection) {
                ObservableCollection<S> collection = (ObservableCollection<S>) relation;
                changes = (CollectionChanges<?, S>) collection.observer();
                if (changes != null) {
                    addedElements = changes.addedElements();
                }
            }
            for (S added : addedElements) {
                S junction = (S) referencedType.getFactory().get();
                EntityProxy<S> junctionProxy = context.proxyOf(junction, false);
                EntityProxy<S> uProxy = context.proxyOf(added, false);
                if (attribute.getCascadeActions().contains(CascadeAction.SAVE)) {
                    cascadeWrite(mode, added, uProxy);
                }
                Object tValue = proxy.get(tRef, false);
                Object uValue = uProxy.get(uRef, false);
                junctionProxy.set(tKey, tValue, PropertyState.MODIFIED);
                junctionProxy.set(uKey, uValue, PropertyState.MODIFIED);
                Cascade cascade = isObservable && mode == Cascade.UPSERT ? Cascade.UPSERT : Cascade.INSERT;
                cascadeWrite(cascade, junction, null);
            }
            if (changes != null) {
                Object keyValue = proxy.get(tRef, false);
                for (S removed : changes.removedElements()) {
                    Object otherValue = context.proxyOf(removed, false).get(uRef);
                    Class<? extends S> removeType = (Class<? extends S>) referencedType.getClassType();
                    Supplier<? extends Scalar<Integer>> query = queryable.delete(removeType).where(tKey.equal(keyValue)).and(uKey.equal(otherValue));
                    int count = query.get().value();
                    if (count != 1) {
                        throw new RowCountException(1, count);
                    }
                }
                changes.clear();
            }
            break;
        case MANY_TO_ONE:
        default:
            break;
    }
    context.read(type.getClassType()).refresh(entity, proxy, attribute);
}
Also used : QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) UPDATE(io.requery.query.element.QueryType.UPDATE) ArrayList(java.util.ArrayList) CollectionChanges(io.requery.proxy.CollectionChanges) ObservableCollection(io.requery.util.ObservableCollection) PersistenceException(io.requery.PersistenceException)

Example 3 with QueryAttribute

use of io.requery.meta.QueryAttribute in project requery by requery.

the class EntityReader method batchRefresh.

@SafeVarargs
final Iterable<E> batchRefresh(Iterable<E> entities, Attribute<E, ?>... attributes) {
    // if the type is immutable return a new collection with the rebuilt objects
    final Collection<E> collection = type.isImmutable() ? new ArrayList<E>() : null;
    if (keyAttribute == null) {
        // non optimal case objects with multiple keys or no keys
        for (E entity : entities) {
            entity = refresh(entity, type.getProxyProvider().apply(entity), attributes);
            if (collection != null) {
                collection.add(entity);
            }
        }
    } else {
        Set<Expression<?>> selection = new LinkedHashSet<>();
        Attribute[] selectAttributes;
        if (attributes == null || attributes.length == 0) {
            selection = defaultSelection;
            selectAttributes = defaultSelectionAttributes;
        } else {
            LinkedHashSet<Attribute> selectedAttributes = new LinkedHashSet<>();
            selection.add(keyAttribute);
            selectedAttributes.add(keyAttribute);
            for (Attribute<E, ?> attribute : attributes) {
                if (attribute.isVersion()) {
                    selection.add(aliasVersion(attribute));
                } else if (!attribute.isAssociation()) {
                    QueryAttribute<E, ?> queryAttribute = Attributes.query(attribute);
                    selection.add(queryAttribute);
                }
                selectedAttributes.add(attribute);
            }
            selectAttributes = selectedAttributes.toArray(new Attribute[selection.size()]);
        }
        Map<Object, EntityProxy<E>> map = new HashMap<>();
        for (E entity : entities) {
            EntityProxy<E> proxy = type.getProxyProvider().apply(entity);
            Object key = proxy.key();
            if (key == null) {
                throw new MissingKeyException();
            }
            map.put(key, proxy);
        }
        Condition<?, ?> condition = Attributes.query(keyAttribute).in(map.keySet());
        if (type.isCacheable()) {
            final Consumer<E> collector = new Consumer<E>() {

                @Override
                public void accept(E e) {
                    if (collection != null) {
                        collection.add(e);
                    }
                }
            };
            // readResult will merge the results into the target object in cache mode
            ResultReader<E> resultReader = newResultReader(selectAttributes);
            SelectOperation<E> select = new SelectOperation<>(context, resultReader);
            QueryElement<? extends Result<E>> query = new QueryElement<>(QueryType.SELECT, context.getModel(), select);
            try (Result<E> result = query.select(selection).where(condition).get()) {
                result.each(collector);
            }
        } else {
            try (Result<Tuple> result = queryable.select(selection).where(condition).get()) {
                for (Tuple tuple : result) {
                    Object key = tuple.get((Expression) keyAttribute);
                    EntityProxy<E> proxy = map.get(key);
                    synchronized (proxy.syncObject()) {
                        for (Expression expression : selection) {
                            Object value = tuple.get(expression);
                            if (expression instanceof AliasedExpression) {
                                AliasedExpression aliased = (AliasedExpression) expression;
                                expression = aliased.getInnerExpression();
                            }
                            Attribute<E, Object> attribute = Attributes.query((Attribute) expression);
                            proxy.set(attribute, value, PropertyState.LOADED);
                        }
                    }
                }
            }
        }
        // associations TODO can be optimized
        if (attributes != null) {
            for (Attribute<E, ?> attribute : attributes) {
                if (attribute.isAssociation()) {
                    for (EntityProxy<E> proxy : map.values()) {
                        refreshAssociation(proxy, attribute);
                    }
                }
            }
        }
    }
    return collection == null ? entities : collection;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) WHERE(io.requery.sql.Keyword.WHERE) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) QueryElement(io.requery.query.element.QueryElement) AliasedExpression(io.requery.query.AliasedExpression) EntityProxy(io.requery.proxy.EntityProxy) Consumer(io.requery.util.function.Consumer) AliasedExpression(io.requery.query.AliasedExpression) Expression(io.requery.query.Expression) QueryAttribute(io.requery.meta.QueryAttribute) Tuple(io.requery.query.Tuple)

Example 4 with QueryAttribute

use of io.requery.meta.QueryAttribute in project requery by requery.

the class EntityDataStore method findByKey.

@Override
public <E extends T, K> E findByKey(Class<E> type, K key) {
    Type<E> entityType = entityModel.typeOf(type);
    if (entityType.isCacheable() && entityCache != null) {
        E entity = entityCache.get(type, key);
        if (entity != null) {
            return entity;
        }
    }
    Set<Attribute<E, ?>> keys = entityType.getKeyAttributes();
    if (keys.isEmpty()) {
        throw new MissingKeyException();
    }
    Selection<? extends Result<E>> selection = select(type);
    if (keys.size() == 1) {
        QueryAttribute<E, Object> attribute = Attributes.query(keys.iterator().next());
        selection.where(attribute.equal(key));
    } else {
        if (key instanceof CompositeKey) {
            CompositeKey compositeKey = (CompositeKey) key;
            for (Attribute<E, ?> attribute : keys) {
                QueryAttribute<E, Object> keyAttribute = Attributes.query(attribute);
                Object value = compositeKey.get(keyAttribute);
                selection.where(keyAttribute.equal(value));
            }
        } else {
            throw new IllegalArgumentException("CompositeKey required");
        }
    }
    return selection.get().firstOrNull();
}
Also used : CompositeKey(io.requery.proxy.CompositeKey) UPDATE(io.requery.query.element.QueryType.UPDATE) DELETE(io.requery.query.element.QueryType.DELETE) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute)

Aggregations

QueryAttribute (io.requery.meta.QueryAttribute)4 Attribute (io.requery.meta.Attribute)3 Expression (io.requery.query.Expression)2 UPDATE (io.requery.query.element.QueryType.UPDATE)2 PersistenceException (io.requery.PersistenceException)1 CollectionChanges (io.requery.proxy.CollectionChanges)1 CompositeKey (io.requery.proxy.CompositeKey)1 EntityProxy (io.requery.proxy.EntityProxy)1 AliasedExpression (io.requery.query.AliasedExpression)1 NamedExpression (io.requery.query.NamedExpression)1 RowExpression (io.requery.query.RowExpression)1 Tuple (io.requery.query.Tuple)1 QueryElement (io.requery.query.element.QueryElement)1 DELETE (io.requery.query.element.QueryType.DELETE)1 Function (io.requery.query.function.Function)1 WHERE (io.requery.sql.Keyword.WHERE)1 ObservableCollection (io.requery.util.ObservableCollection)1 Consumer (io.requery.util.function.Consumer)1 Supplier (io.requery.util.function.Supplier)1 ArrayList (java.util.ArrayList)1