All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jooq.impl.ReferenceImpl Maven / Gradle / Ivy

There is a newer version: 3.19.18
Show newest version
/*
 * 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.
 *
 * Other licenses:
 * -----------------------------------------------------------------------------
 * Commercial licenses for this work are available. These replace the above
 * Apache-2.0 license and offer limited warranties, support, maintenance, and
 * commercial database integrations.
 *
 * For more information, please visit: http://www.jooq.org/licenses
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package org.jooq.impl;

import static org.jooq.impl.DSL.row;
import static org.jooq.impl.Tools.filterOne;
import static org.jooq.impl.Tools.first;
import static org.jooq.impl.Tools.list;
import static org.jooq.impl.Tools.map;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.jooq.ConstraintEnforcementStep;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.RowN;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.exception.DetachedException;
import org.jooq.impl.QOM.UEmpty;

/**
 * @author Lukas Eder
 */
final class ReferenceImpl extends AbstractKey implements ForeignKey, UEmpty {

    private final UniqueKey       uk;
    private final TableField[] ukFields;

    ReferenceImpl(Table table, Name name, TableField[] fkFields, UniqueKey uk, TableField[] ukFields, boolean enforced) {
        super(table, name, fkFields, enforced);

        this.uk = uk;
        this.ukFields = ukFields;
    }

    @Override
    public final UniqueKey getKey() {
        return uk;
    }

    @Override
    public final List> getKeyFields() {
        return Arrays.asList(ukFields);
    }

    @Override
    public final TableField[] getKeyFieldsArray() {
        return ukFields;
    }

    @Override
    public final O fetchParent(R record) {
        return filterOne(fetchParents(record));
    }

    @Override
    @SafeVarargs
    public final Result fetchParents(R... records) {
        return fetchParents(list(records));
    }

    @Override
    public final Result fetchParents(Collection records) {
        if (records == null || records.size() == 0)
            return new ResultImpl<>(new DefaultConfiguration(), uk.getFields());
        else
            return extractDSLContext(records).selectFrom(parents(records)).fetch();
    }

    @Override
    public final Result fetchChildren(O record) {
        return fetchChildren(list(record));
    }

    @Override
    @SafeVarargs
    public final Result fetchChildren(O... records) {
        return fetchChildren(list(records));
    }

    @Override
    public final Result fetchChildren(Collection records) {
        if (records == null || records.size() == 0)
            return new ResultImpl<>(new DefaultConfiguration(), getFields());
        else
            return extractDSLContext(records).selectFrom(children(records)).fetch();
    }

    @Override
    public final Table parent(R record) {
        return parents(list(record));
    }

    @SafeVarargs
    @Override
    public final Table parents(R... records) {
        return parents(list(records));
    }

    @Override
    public final Table parents(Collection records) {
        return table(records, uk.getTable(), uk.getFieldsArray(), getFieldsArray());
    }

    @Override
    public final Table children(O record) {
        return children(list(record));
    }

    @SafeVarargs
    @Override
    public final Table children(O... records) {
        return children(list(records));
    }

    @Override
    public final Table children(Collection records) {
        return table(records, getTable(), getFieldsArray(), uk.getFieldsArray());
    }

    @SuppressWarnings("unchecked")
    private static  Table table(
        Collection records,
        Table table,
        TableField[] fields1,
        TableField[] fields2
    ) {
        // [#11580] Some dialects support foreign keys with shorter column lists
        //          than their referenced primary keys
        TableField[] f1 = truncate(fields1, fields2);
        TableField[] f2 = truncate(fields2, fields1);

        return new InlineDerivedTable<>(
            table,
            f1.length == 1
                ? ((Field) f1[0]).in(extractValues(records, f2[0]))
                : row(f1).in(extractRows(records, f2))
        );
    }

    private static  TableField[] truncate(TableField[] fields1, TableField[] fields2) {
        if (fields1.length <= fields2.length)
            return fields1;
        else
            return Arrays.copyOf(fields1, fields2.length);
    }

    /**
     * Extract a list of values from a set of records given some fields
     */
    private static  List extractValues(Collection records, TableField field2) {
        return map(records, r -> r.get(field2));
    }

    /**
     * Extract a list of row value expressions from a set of records given some fields
     */
    private static  List extractRows(Collection records, TableField[] fields) {
        return map(records, r -> {
            Object[] values = map(fields, f -> r.get(f), Object[]::new);
            return row(values);
        });
    }

    /**
     * Extract a configuration from the first record of a collection of records
     */
    private static  DSLContext extractDSLContext(Collection records) {
        R first = first(records);

        if (first != null)
            return DSL.using(first.configuration());
        else
            throw new DetachedException("Supply at least one attachable record");
    }

    @Override
    final ConstraintEnforcementStep constraint0() {
        return DSL.constraint(getName())
                  .foreignKey(getFieldsArray())
                  .references(uk.getTable(), getKeyFieldsArray());
    }
}