blob: e1c7384ebb376e15adab0b6e22cf67776a47a610 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008 Markus KARG(markus-karg@users.sourceforge.net).
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Markus Karg and Oracle - initial API and implementation from Oracle TopLink and TopLink Essentials
// 05/16/2008-1.0 Markus Karg
// - 237843: CONCAT must be translated into || instead of +
// 02/23/2015-2.6 Dalia Abo Sheasha
// - 460607: Change DatabasePlatform StoredProcedureTerminationToken to be configurable
package org.eclipse.persistence.platform.database;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Hashtable;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.queries.ValueReadQuery;
/**
* Provides SQL Anywhere specific behaviour.
*
* @author Markus KARG (markus-karg@users.sourceforge.net)
*/
public class SQLAnywherePlatform extends SybasePlatform {
public SQLAnywherePlatform() {
super();
this.storedProcedureTerminationToken = ";";
}
// TODO: can't use these field types: none of them has sizes.
// That results is using defaults, that seem to be 9 for VARCHAR
// and neither FeatureTestModel nor AggregateTestModel would setup because of that.
// Untill this is fixed have to use the field types inherited from SybasePlatform.
/* protected Hashtable buildFieldTypes() {
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
protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
Hashtable<Class<?>, FieldTypeDefinition> fieldTypeMapping = super.buildFieldTypes();
fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("BIT", false));
return fieldTypeMapping;
}
/**
* INTERNAL:
* Build the identity query for native sequencing.
*/
@Override
public ValueReadQuery buildSelectQueryForIdentity() {
ValueReadQuery selectQuery = new ValueReadQuery();
StringWriter writer = new StringWriter();
writer.write("SELECT @@IDENTITY");
selectQuery.setSQLString(writer.toString());
return selectQuery;
}
public static ExpressionOperator createCurrentDateOperator() {
return ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.CurrentDate, "CURRENT DATE");
}
public static ExpressionOperator createCurrentTimeOperator() {
return ExpressionOperator.simpleFunctionNoParentheses(ExpressionOperator.CurrentTime, "CURRENT TIME");
}
public static ExpressionOperator createLocate2Operator() {
return ExpressionOperator.simpleThreeArgumentFunction(ExpressionOperator.Locate2, "LOCATE");
}
public static ExpressionOperator createConcatOperator() {
return ExpressionOperator.simpleLogicalNoParens(ExpressionOperator.Concat, "||");
}
public static ExpressionOperator createLocateOperator() {
return ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Locate, "LOCATE");
}
@Override
protected String getCreateTempTableSqlPrefix() {
return "DECLARE LOCAL TEMPORARY TABLE ";
}
/**
* Used for stored procedure creation: Prefix for INPUT parameters.
* Not required on most platforms.
*/
@Override
public String getInputProcedureToken() {
return "IN";
}
@Override
public String getInOutputProcedureToken() {
return "";
}
/* This method is used to print the output parameter token when stored
* procedures is created
*/
@Override
public String getCreationOutputProcedureToken() {
return "OUT";
}
/* This method is used to print the output parameter token when stored
* procedures are called
*/
@Override
public String getOutputProcedureToken() {
return "";
}
@Override
public int getMaxFieldNameSize() {
return 128;
}
/**
* Used for sp defs.
*/
@Override
public String getProcedureArgumentString() {
return "";
}
@Override
public String getStoredProcedureParameterPrefix() {
return "";
}
@Override
public String getProcedureAsString() {
return "";
}
@Override
public String getProcedureBeginString() {
return "BEGIN";
}
@Override
public String getProcedureEndString() {
return "END";
}
/**
* Used for batch writing and sp defs.
*/
@Override
public String getBatchBeginString() {
return "BEGIN ";
}
/**
* Used for batch writing and sp defs.
*/
@Override
public String getBatchEndString() {
return "END;";
}
/**
* Used for batch writing and sp defs.
*/
@Override
public String getBatchDelimiterString() {
return "; ";
}
/**
* Used for sp calls.
*/
@Override
public String getProcedureCallHeader() {
return "CALL ";
}
/**
* Used for sp calls.
*/
@Override
public DatabaseTable getTempTableForTable(DatabaseTable table) {
return new DatabaseTable("$" + table.getName(), table.getTableQualifier(), table.shouldUseDelimiters(), getStartDelimiter(), getEndDelimiter());
}
@Override
protected void initializePlatformOperators() {
super.initializePlatformOperators();
this.addOperator(createConcatOperator());
this.addOperator(createLocateOperator());
this.addOperator(createLocate2Operator());
// this.addOperator(createCurrentDateOperator());
// this.addOperator(createCurrentTimeOperator());
this.addOperator(ExpressionOperator.charLength());
this.addOperator(ExpressionOperator.mod());
}
@Override
public boolean isSQLAnywhere() {
return true;
}
@Override
public boolean isSybase() {
return false;
}
@Override
public boolean requiresProcedureBrackets() {
return true;
}
@Override
public boolean requiresProcedureCallBrackets() {
return true;
}
/**
* INTERNAL:
* Indicates whether the version of CallableStatement.registerOutputParameter method
* that takes type name should be used.
*/
@Override
public boolean requiresTypeNameToRegisterOutputParameter() {
return false;
}
@Override
public void printFieldIdentityClause(Writer writer) throws ValidationException {
try {
writer.write(" DEFAULT AUTOINCREMENT");
} catch (IOException ioException) {
throw ValidationException.fileError(ioException);
}
}
@Override
public void printFieldNullClause(Writer writer) throws ValidationException {
try {
writer.write(" NULL");
} catch (IOException ioException) {
throw ValidationException.fileError(ioException);
}
}
@Override
public boolean shouldPrintInputTokenAtStart() {
return true;
}
@Override
public boolean shouldPrintInOutputTokenBeforeType() {
return false;
}
@Override
public boolean shouldPrintOutputTokenAtStart() {
return true;
}
@Override
public boolean shouldPrintOutputTokenBeforeType() {
return false;
}
//**temp
@Override
public boolean shouldPrintStoredProcedureArgumentNameInCall() {
return false;
}
@Override
public boolean shouldPrintStoredProcedureVariablesAfterBeginString() {
return true;
}
@Override
public boolean supportsIdentity() {
return true;
}
@Override
public boolean supportsLocalTempTables() {
return true;
}
@Override
public boolean supportsStoredFunctions() {
return true;
}
/**
* SQL Anywhere does support cascade on delete, unlike Sybase.
*/
@Override
public boolean supportsDeleteOnCascade() {
return true;
}
}