Package org.datanucleus.store.rdbms.scostore

Source Code of org.datanucleus.store.rdbms.scostore.RDBMSFKArrayStoreSpecialization

/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
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.

Contributors:
    ...
**********************************************************************/
package org.datanucleus.store.rdbms.scostore;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.store.ExecutionContext;
import org.datanucleus.store.ObjectProvider;
import org.datanucleus.store.connection.ManagedConnection;
import org.datanucleus.store.mapped.DatastoreClass;
import org.datanucleus.store.mapped.mapping.JavaTypeMapping;
import org.datanucleus.store.mapped.mapping.MappingHelper;
import org.datanucleus.store.mapped.scostore.ElementContainerStore;
import org.datanucleus.store.mapped.scostore.FKArrayStoreSpecialization;
import org.datanucleus.store.rdbms.RDBMSStoreManager;
import org.datanucleus.store.rdbms.SQLController;
import org.datanucleus.store.rdbms.mapping.RDBMSMapping;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;

/**
* RDBMS-specific implementation of an {@link FKArrayStoreSpecialization}.
*/
public class RDBMSFKArrayStoreSpecialization extends RDBMSAbstractArrayStoreSpecialization implements FKArrayStoreSpecialization
{
    /** Statement for updating a foreign key in a 1-N unidirectional */
    private String updateFkStmt;

    /** Statement for nullifying a FK in the element. */
    private String clearNullifyStmt;

    RDBMSFKArrayStoreSpecialization(Localiser localiser, ClassLoaderResolver clr, RDBMSStoreManager storeMgr)
    {
        super(localiser, clr, storeMgr);
    }

    /**
     * Method to update the element FK to point to the specified owner/index.
     * @param ownerSM StateManager of the owner
     * @param element The element object
     * @param owner The owner we should set the FK to (can be null)
     * @param index Position in the list
     * @param ecs backing store
     * @return whether the FK was updated
     */
    public boolean getUpdateElementFk(ObjectProvider ownerSM, Object element, Object owner, int index,
            ElementContainerStore ecs)
    {
        String updateFkStmt = getUpdateFkStmt(ecs);
        boolean retval;
        ExecutionContext ec = ownerSM.getExecutionContext();
        try
        {
            ManagedConnection mconn = storeMgr.getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            try
            {
                PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, updateFkStmt, false);
                try
                {
                    int jdbcPosition = 1;
                    if (ecs.getElementInfo().length > 1)
                    {
                        DatastoreClass table = storeMgr.getDatastoreClass(element.getClass().getName(), clr);
                        if (table != null)
                        {
                            ps.setString(jdbcPosition++, table.toString());
                        }
                        else
                        {
                            NucleusLogger.PERSISTENCE.info(">> FKArrayStore.updateElementFK : " +
                                "need to set table in statement but dont know table where to store " + element);
                        }
                    }
                    if (owner == null)
                    {
                        JavaTypeMapping ownerMapping = ecs.getOwnerMapping();
                        ownerMapping.setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, ownerMapping), null);
                        jdbcPosition += ownerMapping.getNumberOfDatastoreMappings();
                    }
                    else
                    {
                        jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerSM, ec, ps, jdbcPosition, ecs);
                    }
                    jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, ecs.getOrderMapping());
                    if (ecs.getRelationDiscriminatorMapping() != null)
                    {
                        jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, ecs);
                    }
                    jdbcPosition =
                        BackingStoreHelper.populateElementInStatement(ec, ps, element, jdbcPosition, ecs.getElementMapping());

                    sqlControl.executeStatementUpdate(mconn, updateFkStmt, ps, true);
                    retval = true;
                }
                finally
                {
                    sqlControl.closeStatement(mconn, ps);
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (SQLException e)
        {
            throw new NucleusDataStoreException(localiser.msg("056027", updateFkStmt), e);
        }

        return retval;
    }

    /**
     * Method to clear the array (nulls out all FKs to this owner).
     * @param ownerSM StateManager for the owner
     * @param ecs Backing store
     */
    public void clear(ObjectProvider ownerSM, ElementContainerStore ecs)
    {
        // TODO If the relation is bidirectional we need to clear the owner in the element
        String clearNullifyStmt = getClearNullifyStmt(ecs);
        try
        {
            ExecutionContext ec = ownerSM.getExecutionContext();
            ManagedConnection mconn = ecs.getStoreManager().getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            try
            {
                PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, clearNullifyStmt, false);
                try
                {
                    int jdbcPosition = 1;
                    jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerSM, ec, ps, jdbcPosition, ecs);
                    if (ecs.getRelationDiscriminatorMapping() != null)
                    {
                        BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, ecs);
                    }
                    sqlControl.executeStatementUpdate(mconn, clearNullifyStmt, ps, true);
                }
                finally
                {
                    sqlControl.closeStatement(mconn, ps);
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (SQLException e)
        {
            throw new NucleusDataStoreException(localiser.msg("056013", clearNullifyStmt), e);
        }
    }

    /**
     * Generate statement for updating the owner, index columns in an inverse 1-N.
     * Will result in the statement
     * <PRE>
     * UPDATE ELEMENTTABLE SET FK_COL_1=?, FK_COL_2=?, FK_IDX=? [,DISTINGUISHER=?]
     * WHERE ELEMENT_ID=?
     * </PRE>
     * when we have a single element table, and
     * <PRE>
     * UPDATE ? SET FK_COL_1=?, FK_COL_2=?, FK_IDX=? [,DISTINGUISHER=?]
     * WHERE ELEMENT_ID=?
     * </PRE>
     * when we have multiple element tables possible.
     * @return Statement for updating the owner/index of an element in an inverse 1-N
     */
    private String getUpdateFkStmt(ElementContainerStore ecs)
    {
        if (updateFkStmt == null)
        {
            JavaTypeMapping ownerMapping = ecs.getOwnerMapping();
            JavaTypeMapping orderMapping = ecs.getOrderMapping();
            JavaTypeMapping elementMapping = ecs.getElementMapping();
            JavaTypeMapping relationDiscriminatorMapping = ecs.getRelationDiscriminatorMapping();
            ElementContainerStore.ElementInfo[] elementInfo = ecs.getElementInfo();

            StringBuffer stmt = new StringBuffer();
            stmt.append("UPDATE ");
            if (elementInfo.length > 1)
            {
                stmt.append("?");
            }
            else
            {
                stmt.append(elementInfo[0].getDatastoreClass().toString());
            }
            stmt.append(" SET ");
            for (int i = 0; i < ownerMapping.getNumberOfDatastoreMappings(); i++)
            {
                if (i > 0)
                {
                    stmt.append(",");
                }
                stmt.append(ownerMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                stmt.append(" = ");
                stmt.append(((RDBMSMapping) ownerMapping.getDatastoreMapping(i)).getUpdateInputParameter());
            }
            for (int i = 0; i < orderMapping.getNumberOfDatastoreMappings(); i++)
            {
                stmt.append(",");
                stmt.append(orderMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                stmt.append(" = ");
                stmt.append(((RDBMSMapping) orderMapping.getDatastoreMapping(i)).getUpdateInputParameter());
            }
            if (relationDiscriminatorMapping != null)
            {
                for (int i = 0; i < relationDiscriminatorMapping.getNumberOfDatastoreMappings(); i++)
                {
                    stmt.append(",");
                    stmt.append(
                        relationDiscriminatorMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                    stmt.append(" = ");
                    stmt.append(((RDBMSMapping) relationDiscriminatorMapping.getDatastoreMapping(i)).getUpdateInputParameter());
                }
            }

            stmt.append(" WHERE ");

            for (int i = 0; i < elementMapping.getNumberOfDatastoreMappings(); i++)
            {
                if (i > 0)
                {
                    stmt.append(" AND ");
                }
                stmt.append(elementMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                stmt.append(" = ");
                stmt.append(((RDBMSMapping) elementMapping.getDatastoreMapping(i)).getUpdateInputParameter());
            }
            updateFkStmt = stmt.toString();
        }

        return updateFkStmt;
    }

    /**
     * Generates the statement for clearing items by nulling the owner link out. The statement will be
     * <PRE>
     * UPDATE ARRAYTABLE SET OWNERCOL=NULL, INDEXCOL=NULL [,DISTINGUISHER=NULL]
     * WHERE OWNERCOL=? [AND DISTINGUISHER=?]
     * </PRE>
     * when there is only one element table, and will be
     * <PRE>
     * UPDATE ? SET OWNERCOL=NULL, INDEXCOL=NULL [,DISTINGUISHER=NULL]
     * WHERE OWNERCOL=? [AND DISTINGUISHER=?]
     * </PRE>
     * when there is more than 1 element table.
     * @return The Statement for clearing items for the owner.
     */
    protected String getClearNullifyStmt(ElementContainerStore ecs)
    {
        if (clearNullifyStmt == null)
        {
            JavaTypeMapping ownerMapping = ecs.getOwnerMapping();
            JavaTypeMapping orderMapping = ecs.getOrderMapping();
            JavaTypeMapping relationDiscriminatorMapping = ecs.getRelationDiscriminatorMapping();
            ElementContainerStore.ElementInfo[] elementInfo = ecs.getElementInfo();

            StringBuffer stmt = new StringBuffer();
            stmt.append("UPDATE ");
            if (elementInfo.length > 1)
            {
                stmt.append("?");
            }
            else
            {
                stmt.append(elementInfo[0].getDatastoreClass().toString());
            }
            stmt.append(" SET ");
            for (int i = 0; i < ownerMapping.getNumberOfDatastoreMappings(); i++)
            {
                if (i > 0)
                {
                    stmt.append(", ");
                }
                stmt.append(ownerMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString() + " = NULL");
            }
            for (int i = 0; i < orderMapping.getNumberOfDatastoreMappings(); i++)
            {
                stmt.append(", ");
                stmt.append(orderMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString() + " = NULL");
            }
            if (relationDiscriminatorMapping != null)
            {
                for (int i = 0; i < relationDiscriminatorMapping.getNumberOfDatastoreMappings(); i++)
                {
                    stmt.append(", ");
                    stmt.append(
                        relationDiscriminatorMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString() + " = NULL");
                }
            }

            stmt.append(" WHERE ");
            for (int i = 0; i < ownerMapping.getNumberOfDatastoreMappings(); i++)
            {
                if (i > 0)
                {
                    stmt.append(" AND ");
                }
                stmt.append(ownerMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                stmt.append(" = ");
                stmt.append(((RDBMSMapping) ownerMapping.getDatastoreMapping(i)).getUpdateInputParameter());
            }
            if (relationDiscriminatorMapping != null)
            {
                for (int i = 0; i < relationDiscriminatorMapping.getNumberOfDatastoreMappings(); i++)
                {
                    stmt.append(" AND ");
                    stmt.append(relationDiscriminatorMapping.getDatastoreMapping(i).getDatastoreField().getIdentifier().toString());
                    stmt.append(" = ");
                    stmt.append(((RDBMSMapping) relationDiscriminatorMapping.getDatastoreMapping(i)).getUpdateInputParameter());
                }
            }
            clearNullifyStmt = stmt.toString();
        }
        return clearNullifyStmt;
    }
}
TOP

Related Classes of org.datanucleus.store.rdbms.scostore.RDBMSFKArrayStoreSpecialization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.