Hi Andrew,

oops, my fault! I can't test this sequence manager implementation, because I don't use MSSQL.
Seems we have to override getUniqueValue method of AbstractSM..


I attached a new version of SequenceManagerMSSQLGuidImpl - hope it will pass the apache server ;-)
Can you verify this class?


regards,
Armin

Clute, Andrew wrote:

I recently updated to HEAD of CVS, and it exposed an issue I have within
the AbstractSequenceManager.

I was the original author of the SequenceManagerMSSQLGuidImpl sequence
manager, with it's goal to be to allow the use of MSSQL's unique
identifier as their primary key. When the SequenceManagerMSSQLGuidImpl
was written, the code inside of AbstractSequenceManager (v 1.10) would
do a check of the JDBC type of the primary key field, and the call the
apporpriate getUniqueX field.


Because the MSSQL unique identifiers come back best as VARCHAR's (they
look like this '3C6D40F6-F961-49F2-B7F4-BAAA48B8F1F3'), I had them
defiend as varchar's in the repository, and AbstractSequenceManager
would see that and call the getUniqueString() method on the sequence
manager, and all would be fine. Worked like a charm.

However, the code in AbstractSequenceManager (as of v1.11) now no longer
does that type check, and just assumes that getUniqueLong() will work
and blindly calls that! Opps! That won't work for the
SequenceManagerMSSQLGuidImpl because there is no way to return a long
representation of the GUID string that is returned from MSSQL.

So, that makes SequenceManagerMSSQLGuidImpl broken, as it has no way to
return a valid PrimaryKey.

Is this something we should fix, or am I out of luck now with my
SequenceManagerMSSQLGuidImpl?

Thanks
-Andrew




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



package org.apache.ojb.broker.util.sequence;

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import org.apache.commons.lang.SystemUtils;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.util.JdbcTypesHelper;
import org.apache.ojb.broker.accesslayer.ResultSetAndStatement;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.JdbcType;
import org.apache.ojb.broker.query.Query;

import java.sql.SQLException;


/**
 * An Implementation Class that will retrieve a valid new value
 * for a PK field that is of type 'uniqueidentifier'. Since values
 * for these types are generated through a 'newid()' call to
 * MSSQL Server, this class is only valid for MSSQL Server 7.0 and up.
 * <br/>
 * This SequenceManager can be used for any classes that have their PK
 * defined as a 'uniqueidetifier'
 *
 * @author <a href="mailto:[EMAIL PROTECTED]">Andrew Clute</a>
 * @version $Id: SequenceManagerMSSQLGuidImpl.java,v 1.1 2003/07/31 19:13:20 arminw Exp $
 */
public class SequenceManagerMSSQLGuidImpl extends AbstractSequenceManager
{
    private static final JdbcType JDBC_TYPE_VARCHAR = JdbcTypesHelper.getJdbcTypeByName("varchar");
    /**
     * Constructor used by
     * [EMAIL PROTECTED] org.apache.ojb.broker.util.sequence.SequenceManagerFactory}
     *
     * @param broker  PB instance to perform the
     * id generation.
     */
    public SequenceManagerMSSQLGuidImpl(PersistenceBroker broker)
    {
        super(broker);
    }

    public Object getUniqueValue(FieldDescriptor field) throws SequenceManagerException
    {
        // only works for VARCHAR fields
        if(!field.getJdbcType().equals(JDBC_TYPE_VARCHAR))
        {
            throw new SequenceManagerException("This implementation only works with fields defined" +
                    " as VARCHAR, but given field was " + (field != null ? field.getJdbcType() : null));
        }
        Object result = getUniqueString(field);
        // perform a sql to java conversion here, so that clients do
        // not see any db specific values
        result = field.getFieldConversion().sqlToJava(result);
        return result;
    }

    /**
     * returns a unique String for given field.
     * the returned uid is unique accross all tables.
     */
    protected String getUniqueString(FieldDescriptor field) throws SequenceManagerException
    {
        ResultSetAndStatement rsStmt = null;
        try
        {
            rsStmt = getBrokerForClass().serviceJdbcAccess().executeSQL("select newid()", field.getClassDescriptor(), Query.NOT_SCROLLABLE);
            String returnValue = null;
            if (rsStmt.m_rs.next())
            {
                returnValue = rsStmt.m_rs.getString(1);
            }
            rsStmt.m_rs.close();
            return returnValue;

        }
        catch (PersistenceBrokerException e)
        {
            throw new SequenceManagerException(e);
        }
        catch (SQLException e)
        {
            throw new SequenceManagerException(e);
        }

        finally
        {
            if (rsStmt != null)
                rsStmt.close();
        }
    }

    /**
     * Returns a new unique int for the given Class and fieldname.
     */
    protected int getUniqueId(FieldDescriptor field) throws SequenceManagerException
    {
        throw new SequenceManagerException(
                SystemUtils.LINE_SEPARATOR +
                "Failure attempting to retrieve a Guid for a field that is an int -- field should be returned as a VARCHAR");
    }

    /**
     * Returns a new unique int for the given Class and fieldname.
     */
    protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException
    {
        throw new SequenceManagerException(
                SystemUtils.LINE_SEPARATOR +
                "Failure attempting to retrieve a Guid for a field that is a long -- field should be returned as a VARCHAR");
    }

    /**
     * returns a unique Object for class clazz and field fieldName.
     * the returned Object is unique accross all tables in the extent of clazz.
     */
    protected Object getUniqueObject(FieldDescriptor field) throws SequenceManagerException
    {
        return getUniqueString(field);
    }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to