| /* |
| * 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; |
| } |
| } |