persistence@glassfish.java.net

Re: SQLAnywherePlatform

From: Markus KARG <markus.karg_at_gmx.net>
Date: Fri, 02 Feb 2007 20:38:29 +0100

Tom,
>
> I am copying the persistence list on this reply since there may be
> some people on the list that are interested.
>
> I believe there are two things we have to do.
>
> 1. You had some concerns about the licensing. We need to alleviate
> those concerns. Hopefully some of the Sun folks have made some
> progress and can share it with us.
> 2. We should get your code reviewed. When we all agree that it is in
> shape to check-in we will check it in. To get the code reviewed, I
> beleive the best strategy is to send it to the persistence list and
> request a review. Let me know if that makes sense to you.
there still is the issue with the jConnect bug that Sybase denies to fix
and the failed test "Query.setFirstResult". Is this a problem for
somebody? Maybe Tom knows how we can turn the sequence from "? = a" to
"a = ?" ?

If nobody has a problem with that, I do not see a reason why not to
replace SQLAnyWherePlatform by my SQLAnywherPlatform.

Attached is the code. Please give it a review. :-)

Thanks
Markus


/*
 * Copyright (C) 2007 Markus KARG (markus-karg_at_users.sourceforge.net)
 *
 * This file is part of GlassFish.
 *
 * GlassFish is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * GlassFish is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GlassFish; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

package oracle.toplink.essentials.platform.database;

import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Hashtable;

import oracle.toplink.essentials.exceptions.ValidationException;
import oracle.toplink.essentials.expressions.ExpressionOperator;
import oracle.toplink.essentials.internal.databaseaccess.DatabasePlatform;
import oracle.toplink.essentials.internal.databaseaccess.FieldTypeDefinition;
import oracle.toplink.essentials.internal.helper.ClassConstants;
import oracle.toplink.essentials.internal.helper.DatabaseTable;
import oracle.toplink.essentials.queryframework.ValueReadQuery;

/**
 * Provides SQL Anywhere specific behaviour.
 *
 * @author Markus KARG (markus-karg_at_users.sourceforge.net)
 */
@SuppressWarnings("serial")
public final class SQLAnywherePlatform extends DatabasePlatform {

        private static final ExpressionOperator createCurrentDateOperator() {
                return ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.CurrentDate, "CURRENT DATE");
        }

        private static final ExpressionOperator createCurrentTimeOperator() {
                return ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.CurrentTime, "CURRENT TIME");
        }

        private static final ExpressionOperator createLocate2Operator() {
                return ExpressionOperator.simpleThreeArgumentFunction(ExpressionOperator.Locate2, "LOCATE");
        }

        private static final ExpressionOperator createLocateOperator() {
                return ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Locate, "LOCATE");
        }

        @Override
        protected final Hashtable buildFieldTypes() {
                final Hashtable<Class, FieldTypeDefinition> fieldTypeMapping = new Hashtable<Class, FieldTypeDefinition>();
                fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("BIT", false));
                fieldTypeMapping.put(Integer.class, new FieldTypeDefinition("INTEGER", false));
                fieldTypeMapping.put(Long.class, new FieldTypeDefinition("BIGINT", false));
                fieldTypeMapping.put(Float.class, new FieldTypeDefinition("REAL", false));
                fieldTypeMapping.put(Double.class, new FieldTypeDefinition("DOUBLE", false));
                fieldTypeMapping.put(Short.class, new FieldTypeDefinition("SMALLINT", false));
                fieldTypeMapping.put(Byte.class, new FieldTypeDefinition("SMALLINT", false));
                fieldTypeMapping.put(BigInteger.class, new FieldTypeDefinition("BIGINT", false));
                fieldTypeMapping.put(BigDecimal.class, new FieldTypeDefinition("DOUBLE", false));
                fieldTypeMapping.put(Number.class, new FieldTypeDefinition("DOUBLE", false));
                fieldTypeMapping.put(String.class, new FieldTypeDefinition("VARCHAR"));
                fieldTypeMapping.put(Character.class, new FieldTypeDefinition("CHAR"));
                fieldTypeMapping.put(Byte[].class, new FieldTypeDefinition("LONG BINARY", false));
                fieldTypeMapping.put(Character[].class, new FieldTypeDefinition("LONG VARCHAR", false));
                fieldTypeMapping.put(byte[].class, new FieldTypeDefinition("LONG BINARY", false));
                fieldTypeMapping.put(char[].class, new FieldTypeDefinition("LONG VARCHAR", false));
                fieldTypeMapping.put(Blob.class, new FieldTypeDefinition("LONG BINARY", false));
                fieldTypeMapping.put(Clob.class, new FieldTypeDefinition("LONG VARCHAR", false));
                fieldTypeMapping.put(Date.class, new FieldTypeDefinition("DATE", false));
                fieldTypeMapping.put(Time.class, new FieldTypeDefinition("TIME", false));
                fieldTypeMapping.put(Timestamp.class, new FieldTypeDefinition("TIMESTAMP", false));
                return fieldTypeMapping;
        }

        @Override
        public final ValueReadQuery buildSelectQueryForNativeSequence() {
                return new ValueReadQuery("SELECT @@identity");
        }

        @Override
        protected final String getCreateTempTableSqlPrefix() {
                return "DECLARE TEMPORARY TABLE ";
        }

        @Override
        public final int getJDBCType(final Class javaType) {
                return javaType == ClassConstants.BLOB ? Types.LONGVARBINARY : javaType == ClassConstants.CLOB ? Types.LONGVARCHAR : super.getJDBCType(javaType);
        }

        @Override
        public final int getMaxFieldNameSize() {
                return 128;
        }

        @Override
        public final DatabaseTable getTempTableForTable(final DatabaseTable table) {
                return new DatabaseTable("$" + table.getName(), table.getTableQualifier());
        }

        @Override
        protected final void initializePlatformOperators() {
                super.initializePlatformOperators();
                this.addOperator(SQLAnywherePlatform.createLocateOperator());
                this.addOperator(SQLAnywherePlatform.createLocate2Operator());
                this.addOperator(SQLAnywherePlatform.createCurrentDateOperator());
                this.addOperator(SQLAnywherePlatform.createCurrentTimeOperator());
        }

        @Override
        public final boolean isSQLAnywhere() {
                return true;
        }

        @Override
        public final void printFieldIdentityClause(final Writer writer) throws ValidationException {
                try {
                        writer.write(" DEFAULT AUTOINCREMENT");
                } catch (final IOException ioException) {
                        throw ValidationException.fileError(ioException);
                }
        }

        @Override
        public final void printFieldNullClause(final Writer writer) throws ValidationException {
                try {
                        writer.write(" NULL");
                } catch (final IOException ioException) {
                        throw ValidationException.fileError(ioException);
                }
        }

        @Override
        public final boolean shouldNativeSequenceAcquireValueAfterInsert() {
                return true;
        }

        @Override
        public final boolean supportsLocalTempTables() {
                return true;
        }

        @Override
        public final boolean supportsNativeSequenceNumbers() {
                return true;
        }

        @Override
        public final boolean supportsStoredFunctions() {
                return true;
        }

}