<commit_before>/*
 * Copyright 2016 requery.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.requery.sql;

import io.requery.EntityCache;
import io.requery.PersistenceException;
import io.requery.Queryable;
import io.requery.meta.Attribute;
import io.requery.meta.QueryAttribute;
import io.requery.meta.Type;
import io.requery.proxy.CompositeKey;
import io.requery.proxy.EntityBuilderProxy;
import io.requery.proxy.EntityProxy;
import io.requery.proxy.Initializer;
import io.requery.proxy.PropertyLoader;
import io.requery.proxy.PropertyState;
import io.requery.proxy.QueryInitializer;
import io.requery.proxy.Settable;
import io.requery.query.AliasedExpression;
import io.requery.query.Condition;
import io.requery.query.Expression;
import io.requery.query.Functional;
import io.requery.query.Result;
import io.requery.query.Tuple;
import io.requery.query.WhereAndOr;
import io.requery.query.element.QueryElement;
import io.requery.query.element.QueryType;
import io.requery.util.FilteringIterator;
import io.requery.util.Objects;
import io.requery.util.function.Consumer;
import io.requery.util.function.Predicate;
import io.requery.util.function.Supplier;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static io.requery.sql.Keyword.AS;
import static io.requery.sql.Keyword.FROM;
import static io.requery.sql.Keyword.SELECT;
import static io.requery.sql.Keyword.WHERE;

/**
 * Handles refreshing and loading attributes for {@link io.requery.Entity} instances.
 *
 * @param <E> the entity type
 * @param <S> generic type from which all entities extend
 *
 * @author <NAME>
 */
class EntityReader<E extends S, S> implements PropertyLoader<E> {

    private final EntityCache cache;
    private final Type<E> type;
    private final Mapping mapping;
    private final EntityContext<S> context;
    private final Queryable<S> queryable;
    private final QueryAttribute<E, ?> keyAttribute;
    private final boolean stateless;
    private final boolean cacheable;
    private final Set<Expression<?>> defaultSelection;
    private final Attribute<E, ?>[] defaultSelectionAttributes;

    EntityReader(Type<E> type, EntityContext<S> context, Queryable<S> queryable) {
        this.type = Objects.requireNotNull(type);
        this.context = Objects.requireNotNull(context);
        this.queryable = Objects.requireNotNull(queryable);
        this.cache = this.context.cache();
        this.mapping = this.context.mapping();
        this.stateless = type.isStateless();
        this.cacheable = type.isCacheable();
        // compute default/minimum selections for the type
        LinkedHashSet<Expression<?>> selection = new LinkedHashSet<>();
        LinkedHashSet<Attribute<E, ?>> selectAttributes = new LinkedHashSet<>();
        for (Attribute<E, ?> attribute : type.attributes()) {
            if (!attribute.isLazy() && !attribute.isAssociation()) {
                if (attribute.isVersion()) {
                    Expression<?> expression = aliasVersion(attribute);
                    selection.add(expression);
                } else {
                    selection.add((Expression)attribute);
                }
                selectAttributes.add(attribute);
            }
        }
        defaultSelection = Collections.unmodifiableSet(selection);
        // optimization for single key attribute
        keyAttribute = Attributes.query(type.singleKeyAttribute());
        // attributes converted to array for performance
        defaultSelectionAttributes = Attributes.attributesToArray(selectAttributes,
            new Predicate<Attribute<E, ?>>() {
            @Override
            public boolean test(Attribute<E, ?> value) {
                return true;
            }
        });
    }

    Set<Expression<?>> defaultSelection() {
        return defaultSelection;
    }<commit_msg>Resolve #147 Include foreign key in default selection<commit_after>/*
 * Copyright 2016 requery.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.requery.sql;

import io.requery.EntityCache;
import io.requery.PersistenceException;
import io.requery.Queryable;
import io.requery.meta.Attribute;
import io.requery.meta.QueryAttribute;
import io.requery.meta.Type;
import io.requery.proxy.CompositeKey;
import io.requery.proxy.EntityBuilderProxy;
import io.requery.proxy.EntityProxy;
import io.requery.proxy.Initializer;
import io.requery.proxy.PropertyLoader;
import io.requery.proxy.PropertyState;
import io.requery.proxy.QueryInitializer;
import io.requery.proxy.Settable;
import io.requery.query.AliasedExpression;
import io.requery.query.Condition;
import io.requery.query.Expression;
import io.requery.query.Functional;
import io.requery.query.Result;
import io.requery.query.Tuple;
import io.requery.query.WhereAndOr;
import io.requery.query.element.QueryElement;
import io.requery.query.element.QueryType;
import io.requery.util.FilteringIterator;
import io.requery.util.Objects;
import io.requery.util.function.Consumer;
import io.requery.util.function.Predicate;
import io.requery.util.function.Supplier;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static io.requery.sql.Keyword.AS;
import static io.requery.sql.Keyword.FROM;
import static io.requery.sql.Keyword.SELECT;
import static io.requery.sql.Keyword.WHERE;

/**
 * Handles refreshing and loading attributes for {@link io.requery.Entity} instances.
 *
 * @param <E> the entity type
 * @param <S> generic type from which all entities extend
 *
 * @author <NAME>
 */
class EntityReader<E extends S, S> implements PropertyLoader<E> {

    private final EntityCache cache;
    private final Type<E> type;
    private final Mapping mapping;
    private final EntityContext<S> context;
    private final Queryable<S> queryable;
    private final QueryAttribute<E, ?> keyAttribute;
    private final boolean stateless;
    private final boolean cacheable;
    private final Set<Expression<?>> defaultSelection;
    private final Attribute<E, ?>[] defaultSelectionAttributes;

    EntityReader(Type<E> type, EntityContext<S> context, Queryable<S> queryable) {
        this.type = Objects.requireNotNull(type);
        this.context = Objects.requireNotNull(context);
        this.queryable = Objects.requireNotNull(queryable);
        this.cache = this.context.cache();
        this.mapping = this.context.mapping();
        this.stateless = type.isStateless();
        this.cacheable = type.isCacheable();
        // compute default/minimum selections for the type
        LinkedHashSet<Expression<?>> selection = new LinkedHashSet<>();
        LinkedHashSet<Attribute<E, ?>> selectAttributes = new LinkedHashSet<>();
        for (Attribute<E, ?> attribute : type.attributes()) {
            if (!attribute.isLazy() && (!attribute.isAssociation() || attribute.isForeignKey())) {
                if (attribute.isVersion()) {
                    Expression<?> expression = aliasVersion(attribute);
                    selection.add(expression);
                } else {
                    selection.add((Expression)attribute);
                }
                selectAttributes.add(attribute);
            }
        }
        defaultSelection = Collections.unmodifiableSet(selection);
        // optimization for single key attribute
        keyAttribute = Attributes.query(type.singleKeyAttribute());
        // attributes converted to array for performance
        defaultSelectionAttributes = Attributes.attributesToArray(selectAttributes,
            new Predicate<Attribute<E, ?>>() {
            @Override
            public boolean test(Attribute<E, ?> value) {
                return true;
            }
        });
    }

    Set<Expression<?>> defaultSelection() {
        return defaultSelection;
    }
{'fraction_non_alphanumeric': 0.1020145735105015, 'fraction_numerical': 0.0020360051435919417, 'mean_word_length': 3.5283842794759823, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3104196', 'n_tokens_mistral': 2533, 'n_tokens_neox': 2495, 'n_words': 664}