org.eclipse.persistence.platform.database.PervasivePlatform Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 180e602
/*******************************************************************************
* Copyright (c) 2012, 2014 Pervasive Software Inc, Oracle and/or its affiliates. All Rights Reserved
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Peter Lohman - initial implementation
*
******************************************************************************/
/*
For minimal implementation, compare with:
C:\PL\JPA\EclipseLink\SVN\org.eclipse.persistence\foundation\org.eclipse.persistence.core\src\org\eclipse\persistence\platform\database\CloudscapePlatform.java
For PVSW data type mapping, see: getColumnClassName():C:\cmsynergy\psql11.20_pnl\psql\comp\sdk\jdbc\pvjdbc2\src\com\pervasive\jdbc\v2\ResultSetMetaData.java
*/
package org.eclipse.persistence.platform.database;
import java.util.*;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import java.io.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.tools.schemaframework.FieldDefinition;
import org.eclipse.persistence.queries.*;
/** Purpose: Provides Pervasive SQL DBMS specific behavior.
*
*
* Pervasive SQL Platform file
* Contributed by: Pervasive Software, Inc.
* Contributed under bug: 392109
*
*
* Developed on Pervasive PSQL Server 11.30
*
*
* - Eclipselink Core SRG Test passes with known limitations.
*
- Eclipselink JPA SRG Test passes with known limitations.
*
- Eclipselink stored procedure tests "CustomSQLTestModel", "StoredProcedureGeneratorModel" pass with known limitations.
*
*
*
* Limitations
*
* - Updates are not supported on joined queries or queries with group by.
*
- The platform method getSelectForUpdateString() currently returns an empty string. This is
* to avoid avoid joined queries with FOR UPDATE in them, which Pervasive does not support.
*
- Columns used in indexes must total no more than 255 bytes in length.
*
- Pervasive SQL does not support dynamic parameters in the SELECT list.
*
- IDENTITY columns are either 2- or 4-byte integers. Foreign keys referencing such columns must use the same datatypes.
*
*
**/
public class PervasivePlatform extends org.eclipse.persistence.platform.database.DatabasePlatform {
public static final int DEFAULT_CHAR_SIZE = 80;
//
// Cloned from AccessPlatform.java
//
protected Map buildClassTypes() {
Map classTypeMapping = super.buildClassTypes();
// Causes BLOB to translate to LONGVARBINARY(via java.sql.Blob) instead of BINARY (via Byte[])
classTypeMapping.put("BLOB", java.sql.Blob.class);
return classTypeMapping;
}
protected Hashtable buildFieldTypes() {
Hashtable fieldTypeMapping;
fieldTypeMapping = new Hashtable();
fieldTypeMapping.put(String.class, new FieldTypeDefinition("VARCHAR", DEFAULT_CHAR_SIZE));
// fieldTypeMapping.put(java.math.BigDecimal.class, new FieldTypeDefinition("BIGINT", false));
fieldTypeMapping.put(java.math.BigInteger.class, new FieldTypeDefinition("BIGINT", false));
fieldTypeMapping.put(Integer.class, new FieldTypeDefinition("INTEGER", false));
fieldTypeMapping.put(Long.class, new FieldTypeDefinition("INTEGER", false));
fieldTypeMapping.put(Short.class, new FieldTypeDefinition("SMALLINT", false));
fieldTypeMapping.put(Byte.class, new FieldTypeDefinition("TINYINT", false));
fieldTypeMapping.put(Float.class, new FieldTypeDefinition("REAL", false));
fieldTypeMapping.put(Double.class, new FieldTypeDefinition("DOUBLE", false));
fieldTypeMapping.put(Character.class, new FieldTypeDefinition("CHAR", 1));
fieldTypeMapping.put(java.sql.Date.class, new FieldTypeDefinition("DATE", false));
fieldTypeMapping.put(java.sql.Time.class, new FieldTypeDefinition("TIME", false));
fieldTypeMapping.put(java.sql.Timestamp.class, new FieldTypeDefinition("TIMESTAMP", false));
fieldTypeMapping.put(byte[].class, new FieldTypeDefinition("BINARY", DEFAULT_CHAR_SIZE ));
fieldTypeMapping.put(Byte[].class, new FieldTypeDefinition("LONGVARBINARY", false));
fieldTypeMapping.put(Character[].class, new FieldTypeDefinition("CHAR", DEFAULT_CHAR_SIZE));
fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("BIT", false));
fieldTypeMapping.put(java.sql.Blob.class, new FieldTypeDefinition("LONGVARBINARY", false));
fieldTypeMapping.put(java.sql.Clob.class, new FieldTypeDefinition("LONGVARCHAR", false));
fieldTypeMapping.put(java.math.BigDecimal.class, new FieldTypeDefinition("DECIMAL",38, 0)); // From MySQL
fieldTypeMapping.put(Number.class, new FieldTypeDefinition("DECIMAL",38,0)); // From MySQL
// fieldTypeMapping.put(java.lang.Number.class, new FieldTypeDefinition("BIGINT", false));
fieldTypeMapping.put(char[].class, new FieldTypeDefinition("LONGVARCHAR", false));
fieldTypeMapping.put(java.util.Calendar.class, new FieldTypeDefinition("TIMESTAMP"));
fieldTypeMapping.put(java.util.Date.class, new FieldTypeDefinition("TIMESTAMP"));
return fieldTypeMapping;
}
/**
*
* Pervasive uses the INOUT keyword, as opposed to "IN OUT".
*/
@Override
public String getInOutputProcedureToken() {
return "INOUT";
}
/**
* Pervasive uses IN prefix for INPUT parameters.
*
*/
@Override
public String getInputProcedureToken() {
return "IN";
}
/**
* Pervasive uses ":" as prefix for procedure arguments.
*/
public String getProcedureArgumentString() {
return ":";
}
/**
*
* Pervasive requires BEGIN in a procedure statement.
*/
@Override
public String getProcedureBeginString() {
return "BEGIN ";
}
/**
* In CREATE PROCEDURE, Pervasive requires brackets after the procedure name, even if there are no arguments.
*/
public boolean requiresProcedureBrackets() {
return true;
}
/**
* Pervasive uses CALL or EXECUTE not CALL PROCEDURE or EXECUTE PROCEDURE
*/
public String getProcedureCallHeader() {
return "CALL ";
}
/**
*
* Pervasive requires END in a procedure statement.
*/
@Override
public String getProcedureEndString() {
return "END";
}
/**
* Pervasive uses ":" as prefix for procedure parameters.
*/
public String getStoredProcedureParameterPrefix() {
return ":";
}
/**
* Pervasive requires the OUTPUT keyword for output parameters
*/
@Override
public boolean requiresProcedureCallOuputToken() {
return true;
}
protected void initializePlatformOperators() {
super.initializePlatformOperators();
addOperator(ExpressionOperator.simpleThreeArgumentFunction(ExpressionOperator.Substring, "SUBSTRING"));
addOperator(singleArgumentSubstringOperator());
addOperator(ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Nvl, "ISNULL"));
addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.Ceil, "CEILING"));
addOperator(toNumberOperator());
addOperator(toCharOperator());
addOperator(toDateOperator());
}
/**
* Cloned from MySQLPlatform.java
*
*/
/**
* INTERNAL:
* Pervasive SQL stored procedure calls do not require the argument name be printed in the call string
* e.g. call MyStoredProc(?) instead of call MyStoredProc(myvariable = ?)
*/
@Override
public boolean shouldPrintStoredProcedureArgumentNameInCall(){
return false;
}
protected ExpressionOperator toNumberOperator() {
ExpressionOperator exOperator = new ExpressionOperator();
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.ToNumber);
Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
v.addElement("CONVERT(");
v.addElement(", SQL_NUMERIC)");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}
/**
* Cloned from MySQLPlatform.java
*/
protected ExpressionOperator toDateOperator() {
ExpressionOperator exOperator = new ExpressionOperator();
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.ToDate);
Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
v.addElement("CONVERT(");
v.addElement(", DATETIME)");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}
/**
* Cloned from MySQLPlatform.java
*/
protected ExpressionOperator toCharOperator() {
ExpressionOperator exOperator = new ExpressionOperator();
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.ToChar);
Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
v.addElement("CONVERT(");
v.addElement(", SQL_CHAR)");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}
/**
*
* Cloned from MySQLPlatform.java
*/
protected ExpressionOperator dateToStringOperator() {
ExpressionOperator exOperator = new ExpressionOperator();
exOperator.setType(ExpressionOperator.FunctionOperator);
exOperator.setSelector(ExpressionOperator.DateToString);
Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
v.addElement("CONVERT(");
v.addElement(", SQL_CHAR)");
exOperator.printsAs(v);
exOperator.bePrefix();
exOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return exOperator;
}
/**
* Answers whether platform is Pervasive
*/
public boolean isPervasive() {
return true;
}
/**
* JDBC defines an outer join syntax which many drivers do not support. So we normally avoid it.
*/
public boolean shouldUseJDBCOuterJoinSyntax() {
return false; // not sure about this
}
/** Append the receiver's field 'identity' constraint clause to
* a writer.
*
* Taken from
* org.eclipse.persistence\foundation\org.eclipse.persistence.core\src\org\eclipse\persistence\platform\database\AccessPlatform.java
*/
public void printFieldIdentityClause(Writer writer) throws ValidationException {
try {
writer.write(" IDENTITY");
} catch (IOException ioException) {
throw ValidationException.fileError(ioException);
}
}
/**
* Override the default SubstringSingleArg operator.
* Cloned from SybasePlatform.java
*/
public ExpressionOperator singleArgumentSubstringOperator() {
ExpressionOperator result = new ExpressionOperator();
result.setSelector(ExpressionOperator.SubstringSingleArg);
result.setType(ExpressionOperator.FunctionOperator);
Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
v.addElement("SUBSTRING(");
v.addElement(",");
v.addElement(", CHAR_LENGTH(");
v.addElement("))");
result.printsAs(v);
int[] indices = new int[3];
indices[0] = 0;
indices[1] = 1;
indices[2] = 0;
result.setArgumentIndices(indices);
result.setNodeClass(ClassConstants.FunctionExpression_Class);
result.bePrefix();
return result;
}
/**
*
* Indicates whether the platform supports identity.
*
*/
public boolean supportsIdentity() {
return true;
}
//
// Most Temp Table settings cloned from SQLServerPlatform.java
//
/**
* INTERNAL:
*/
public boolean supportsLocalTempTables() {
return true;
}
public boolean supportsGlobalTempTables() {
return true;
}
/**
* INTERNAL:
*/
protected String getCreateTempTableSqlPrefix() {
return "CREATE TABLE ";
}
/**
* INTERNAL:
*/
public DatabaseTable getTempTableForTable(DatabaseTable table) {
return new DatabaseTable("#" + table.getName(), table.getTableQualifier(), table.shouldUseDelimiters(), getStartDelimiter(), getEndDelimiter());
}
/**
*
* Taken from org.eclipse.persistence\foundation\org.eclipse.persistence.core\src\org\eclipse\persistence\platform\database\AccessPlatform.java
*/
public void printFieldTypeSize(Writer writer, FieldDefinition field,FieldTypeDefinition fieldType, boolean shouldPrintFieldIdentityClause) throws IOException {
if (!shouldPrintFieldIdentityClause) {
// if type requires both precision and scale: NUMERIC, DECIMAL
if ((fieldType.getName().equals("NUMERIC")) || (fieldType.getName().equals("DECIMAL"))) {
writer.write(fieldType.getName());
writer.write("(");
if (field.getSize() == 0) {
writer.write(Integer.valueOf(fieldType.getDefaultSize()).toString());
} else {
writer.write(Integer.valueOf(field.getSize()).toString());
}
writer.write(",");
if (field.getSubSize() != 0) {
writer.write(Integer.valueOf(field.getSubSize()).toString());
} else {
writer.write(Integer.valueOf(fieldType.getDefaultSubSize()).toString());
}
writer.write(")");
} else {
super.printFieldTypeSize(writer, field, fieldType,
shouldPrintFieldIdentityClause);
}
}
}
/**
* INTERNAL:
* Build the identity query for native sequencing.
*
* Taken verbatim from org.eclipse.persistence\foundation\org.eclipse.persistence.core\src\org\eclipse\persistence\platform\database\SQLServerPlatform.java
*
*/
@Override
public ValueReadQuery buildSelectQueryForIdentity() {
ValueReadQuery selectQuery = new ValueReadQuery();
selectQuery.setSQLString("SELECT @@IDENTITY");
return selectQuery;
}
/**
* Temporary workaround to avoid joined queries with FOR UPDATE
* in them
*
*/
public String getSelectForUpdateString() {
return "";
}
/**
* INTERNAL:
* Indicates whether SELECT DISTINCT ... FOR UPDATE is allowed by the platform (Oracle doesn't allow this).
*/
public boolean isForUpdateCompatibleWithDistinct() {
return false;
}
/**
* Setting this to false (cf. Sybase) to work around problem
* that unspecified default delete rule is RESTRICT, even when
* not allowed due to self-referencing table.
*/
@Override
public boolean supportsDeleteOnCascade() {
return true;
}
/** Attempts to remove FOR UPDATE from queries */
@Override
public boolean shouldPrintLockingClauseAfterWhereClause() {
return false;
}
/**
* INTERNAL:
* Indicates whether locking clause could be applied to the query that has more than one table
*/
public boolean supportsLockingQueriesWithMultipleTables() {
return false;
}
}