/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.jdo.spi.persistence.support.sqlstore.database;
import com.sun.jdo.api.persistence.support.JDOFatalInternalException;
import com.sun.jdo.api.persistence.support.JDOFatalUserException;
import com.sun.jdo.api.persistence.support.JDOUserException;
import com.sun.jdo.api.persistence.support.SpecialDBOperation;
import com.sun.jdo.spi.persistence.support.sqlstore.LogHelperSQLStore;
import com.sun.jdo.spi.persistence.utility.FieldTypeEnumeration;
import com.sun.jdo.spi.persistence.utility.I18NHelper;
import com.sun.jdo.spi.persistence.utility.PropertyHelper;
import com.sun.jdo.spi.persistence.utility.database.DBVendorTypeHelper;
import com.sun.jdo.spi.persistence.utility.logging.Logger;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.DatabaseMetaData;
import java.util.HashMap;
import java.util.Properties;
import java.util.ResourceBundle;
/**
*/
public class DBVendorType {
/**
* Map from property name to property value.
*/
private HashMap dbMap;
/**
* Instance of specialDBOperation for this vendor type. Please look at
* newSpecialDBOperationInstance() to find out how this member is
* initialized.
*/
private SpecialDBOperation specialDBOperation;
private static final SpecialDBOperation DEFAULT_SPECIAL_DB_OPERATION =
new BaseSpecialDBOperation();
/**
* VendorType as returned from {@link DBVendorTypeHelper#getDBType(java.lang.String)}
*/
private String vendorType;
/**
* VendorType as returned from {@link DBVendorTypeHelper#getEnumDBType(java.lang.String)}
*/
private int enumVendorType;
/**
* The logger
*/
private final static Logger logger;
/**
* I18N message handler
*/
private final static ResourceBundle messages;
/**
* Default properties
*/
private static Properties defaultProperties;
private final static String EXT = ".properties"; // NOI18N
private final static String SPACE = " "; // NOI18N
private final static String NONE = ""; // NOI18N
private final static String PATH = "com/sun/jdo/spi/persistence/support/sqlstore/database/"; // NOI18N
private final static String PROPERTY_OVERRIDE_FILE = ".tpersistence.properties"; // NOI18N
private final static String FOR_UPDATE = "FOR_UPDATE"; // NOI18N
private final static String HOLDLOCK = "HOLDLOCK"; //NOI18N
private final static String SUPPORTS_UPDATE_LOCK = "SUPPORTS_UPDATE_LOCK"; //NOI18N
private final static String SUPPORTS_LOCK_COLUMN_LIST = "SUPPORTS_LOCK_COLUMN_LIST"; //NOI18N
private final static String SUPPORTS_DISTINCT_WITH_UPDATE_LOCK = "SUPPORTS_DISTINCT_WITH_UPDATE_LOCK"; //NOI18N
private final static String NATIVE_OUTER_JOIN = "NATIVE_OUTER_JOIN"; //NOI18N
private final static String LEFT_JOIN = "LEFT_JOIN"; //NOI18N
private final static String LEFT_JOIN_APPEND = "LEFT_JOIN_APPEND"; //NOI18N
private final static String RIGHT_JOIN = "RIGHT_JOIN"; //NOI18N
private final static String RIGHT_JOIN_PRE = "RIGHT_JOIN_PRE"; //NOI18N
private final static String IS_NULL = "IS_NULL"; //NOI18N
private final static String IS_NOT_NULL = "IS_NOT_NULL"; //NOI18N
private final static String ANSI_TRIM = "ANSI_TRIM"; //NOI18N
private final static String RTRIM = "RTRIM"; //NOI18N
private final static String RTRIM_POST = "RTRIM_POST"; //NOI18N
private final static String TABLE_LIST_START = "TABLE_LIST_START"; //NOI18N
private final static String TABLE_LIST_END = "TABLE_LIST_END"; //NOI18N
private final static String STRING_CONCAT = "STRING_CONCAT"; //NOI18N
private final static String QUOTE_CHAR_START = "QUOTE_CHAR_START"; //NOI18N
private final static String QUOTE_CHAR_END = "QUOTE_CHAR_END"; //NOI18N
private final static String QUOTE_SPECIAL_ONLY = "QUOTE_SPECIAL_ONLY"; //NOI18N
private final static String CHAR_LENGTH = "CHAR_LENGTH"; //NOI18N
private final static String SQRT = "SQRT"; //NOI18N
private final static String ABS = "ABS"; //NOI18N
private final static String SUBSTRING = "SUBSTRING"; //NOI18N
private final static String SUBSTRING_FROM = "SUBSTRING_FROM"; //NOI18N
private final static String SUBSTRING_FOR = "SUBSTRING_FOR"; //NOI18N
private final static String POSITION = "POSITION"; //NOI18N
private final static String POSITION_SEP = "POSITION_SEP"; //NOI18N
private final static String POSITION_SEARCH_SOURCE = "POSITION_SEARCH_SOURCE"; //NOI18N
private final static String POSITION_THREE_ARGS = "POSITION_THREE_ARGS"; //NOI18N
private final static String MAP_EMPTY_STRING_TO_NULL = "MAP_EMPTY_STRING_TO_NULL"; //NOI18N
private final static String SPECIAL_DB_OPERATION = "SPECIAL_DB_OPERATION"; //NOI18N
private final static String SUPPORTS_LIKE_ESCAPE = "SUPPORTS_LIKE_ESCAPE"; //NOI18N
private final static String LEFT_LIKE_ESCAPE = "LEFT_LIKE_ESCAPE"; //NOI18N
private final static String RIGHT_LIKE_ESCAPE = "RIGHT_LIKE_ESCAPE"; //NOI18N
private final static String NULL_COMPARISON_FUNCTION_NAME = "NULL_COMPARISON_FUNCTION_NAME"; //NOI18N
private final static String MOD_FUNCTION_NAME = "MOD_FUNCTION_NAME"; //NOI18N
private final static String CONCAT_CAST = "CONCAT_CAST"; //NOI18N
private final static String PARAMETER_CAST = "PARAMETER_CAST"; //NOI18N
private final static String INLINE_NUMERIC = "INLINE_NUMERIC"; //NOI18N
private static final String[] props = new String[] { FOR_UPDATE,
HOLDLOCK, SUPPORTS_UPDATE_LOCK, SUPPORTS_LOCK_COLUMN_LIST,
SUPPORTS_DISTINCT_WITH_UPDATE_LOCK,
NATIVE_OUTER_JOIN, LEFT_JOIN, LEFT_JOIN_APPEND, RIGHT_JOIN, RIGHT_JOIN_PRE,
IS_NULL, IS_NOT_NULL, ANSI_TRIM, RTRIM, RTRIM_POST,
TABLE_LIST_START, TABLE_LIST_END,
QUOTE_CHAR_START, QUOTE_CHAR_END, QUOTE_SPECIAL_ONLY,
STRING_CONCAT, CHAR_LENGTH, SQRT, ABS,
SUBSTRING, SUBSTRING_FROM, SUBSTRING_FOR,
POSITION, POSITION_SEP, POSITION_SEARCH_SOURCE, POSITION_THREE_ARGS,
MAP_EMPTY_STRING_TO_NULL, SPECIAL_DB_OPERATION,
SUPPORTS_LIKE_ESCAPE, LEFT_LIKE_ESCAPE, RIGHT_LIKE_ESCAPE,
NULL_COMPARISON_FUNCTION_NAME, MOD_FUNCTION_NAME,
CONCAT_CAST, PARAMETER_CAST, INLINE_NUMERIC
};
/**
* Initialize static fields.
*/
static {
logger = LogHelperSQLStore.getLogger();
messages = I18NHelper.loadBundle(
"com.sun.jdo.spi.persistence.support.sqlstore.Bundle", // NOI18N
DBVendorType.class.getClassLoader());
defaultProperties = initializeDefaultProperties();
}
/**
* @param databaseMetaData Instance of DatabaseMetaData
* @param identifier identifier of the caller creating a new instance
* of SQLStoreManager.
*/
public DBVendorType(DatabaseMetaData databaseMetaData, String identifier)
throws SQLException {
String vendorName = databaseMetaData.getDatabaseProductName();
String vendorType = DBVendorTypeHelper.getDBType(vendorName);
if (logger.isLoggable()) {
Object[] items = new Object[] {vendorName,vendorType};
logger.fine("sqlstore.database.dbvendor.vendorname", items); // NOI18N
}
this.vendorType = vendorType;
enumVendorType = DBVendorTypeHelper.getEnumDBType(vendorType);
dbMap = getDBPropertiesMap(vendorType,vendorName);
specialDBOperation = newSpecialDBOperationInstance((String)dbMap.get(SPECIAL_DB_OPERATION),
databaseMetaData, identifier);
}
/**
* get properties map for given vendorType and vendorName
*/
private static HashMap getDBPropertiesMap(String vendorType, String vendorName) {
//Initialize returned map to default
HashMap dbHashMap = new HashMap(defaultProperties);
Properties dbProperties = loadDBProperties(vendorType, vendorName);
dbHashMap.putAll(dbProperties);
return dbHashMap;
}
/**
* Initialize default properties.
*/
private static Properties initializeDefaultProperties() {
//Load default properties if not already loaded
if (defaultProperties == null) {
// Load default (sql92) Properties
defaultProperties = new Properties();
try {
loadFromResource(DBVendorTypeHelper.DEFAULT_DB, defaultProperties);
} catch (IOException e) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"sqlstore.database.dbvendor.cantloadDefaultProperties"), // NOI18N
e);
}
}
return defaultProperties;
}
/**
* Load properties for database specified by vendorType and vendorName
*/
private static Properties loadDBProperties(String vendorType, String vendorName) {
// Load actual Properties. Even if it is unknown db,
Properties dbProperties = new Properties();
if (!vendorType.equals(DBVendorTypeHelper.DEFAULT_DB)) {
try {
loadFromResource(vendorType, dbProperties);
} catch (IOException e) {
// else ignore
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.init.default", vendorType); // NOI18N
}
}
}
overrideProperties(dbProperties, vendorName);
return dbProperties;
}
/**
* Overrides default properties with the ones provided
* by the user
*/
private static void overrideProperties(Properties dbProperties, String vendorName) {
boolean debug = logger.isLoggable();
Properties overridingProperties = new Properties();
try {
PropertyHelper.loadFromFile(overridingProperties, PROPERTY_OVERRIDE_FILE);
} catch (Exception e) {
if (debug) {
logger.fine("sqlstore.database.dbvendor.overrideproperties"); // NOI18N
}
return; // nothing to override
}
//Prepare a clean vendor name by replacing all ' ' and '/' with underscores.
String cleanVendorName = vendorName.toLowerCase().replace(' ', '_');
cleanVendorName = cleanVendorName.replace('/', '_');
String propertyPrefix = "database." + cleanVendorName + "."; // prefix // NOI18N
for (int i = 0; i < props.length; i++) {
String o = overridingProperties.getProperty(propertyPrefix + props[i]);
if (o != null) {
if (debug) {
Object[] items = new Object[] {props[i],o};
logger.fine("sqlstore.database.dbvendor.overrideproperties.with", items); // NOI18N
}
dbProperties.setProperty(props[i], o);
}
}
}
/**
* loads database properties list from the specified resource
* into specified Properties object.
* @param resourceName Name of resource.
* @param properties Properties object to load
*/
private static void loadFromResource(String resourceName, Properties properties)
throws IOException {
String fullResourceName = PATH + resourceName + EXT;
PropertyHelper.loadFromResource(properties, fullResourceName, DBVendorType.class.getClassLoader());
}
/**
* Returns new instance of class specified by specialDBOpClassName.
* The class is required to implement interface SpecialDBOperation.
* If specialDBOpClassName is null or cannot be loaded, then an instance
* of BaseSpecialDBOperation is returned.
* @param specialDBOpClassName Name of a class that implements
* SpecialDBOperation
* @param databaseMetaData DatabaseMetaData for the connection for which
* this SpecialDBOperation is created
* @param identifier Identifier of pmf used to obtain databaseMetaData.
* This can be null in non managed environment.
* @return An instance of SpecialDBOperation specified by specialDBOpClassName.
*/
private SpecialDBOperation newSpecialDBOperationInstance(
final String specialDBOpClassName, DatabaseMetaData databaseMetaData,
String identifier) {
SpecialDBOperation retInstance = null;
if (specialDBOpClassName != null) {
final ClassLoader loader = DBVendorType.class.getClassLoader();
Class clz = (Class)java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
try {
if (loader != null) {
return Class.forName(specialDBOpClassName,
true, loader);
} else {
return Class.forName(specialDBOpClassName);
}
} catch(Exception ex) {
if (logger.isLoggable()) {
logger.log(Logger.INFO,
"core.configuration.cantloadclass", // NOI18N
specialDBOpClassName);
}
return null;
}
}
}
);
if (clz != null) {
try {
retInstance = (SpecialDBOperation)clz.newInstance();
retInstance.initialize(databaseMetaData, identifier);
} catch(Exception ex) {
throw new JDOFatalUserException(
I18NHelper.getMessage(messages,
"sqlstore.database.dbvendor.cantinstantiateclass", // NOI18N
specialDBOpClassName), ex);
}
}
}
return (retInstance != null)? retInstance : DEFAULT_SPECIAL_DB_OPERATION;
}
/**
* Returns the string that represents "left join" clause
* for this database
*/
public String getLeftJoin() {
String s = (String)dbMap.get(LEFT_JOIN);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getleftjoin", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns true if this database supports update lock
*/
public boolean isUpdateLockSupported() {
String s = (String)dbMap.get(SUPPORTS_UPDATE_LOCK);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isupdatelocksupported", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if this database supports update 'of column list'
*/
public boolean isLockColumnListSupported() {
String s = (String)dbMap.get(SUPPORTS_LOCK_COLUMN_LIST);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.islockcolumnlistsupported", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if this database supports distinct clause with update lock
*/
public boolean isDistinctSupportedWithUpdateLock() {
String s = (String)dbMap.get(SUPPORTS_DISTINCT_WITH_UPDATE_LOCK);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isdistinctupdatelocksupported", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns the string that represents "holdlock" clause
* for this database
*/
public String getHoldlock() {
String s = (String)dbMap.get(HOLDLOCK);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getholdlock", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns true if the this database needs native outer join semantics.
*/
public boolean isNativeOuterJoin() {
String s = (String)dbMap.get(NATIVE_OUTER_JOIN);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isNativeOuterJoin", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns the string that represents postfix for "left join" clause
* for this database
*/
public String getLeftJoinPost() {
String s = (String)dbMap.get(LEFT_JOIN_APPEND);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getleftjoinpost", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents "right join" clause
* for this database
*/
public String getRightJoin() {
String s = (String)dbMap.get(RIGHT_JOIN);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getrightjoin", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents prefix for "right join" clause
* for this database
*/
public String getRightJoinPre() {
String s = (String)dbMap.get(RIGHT_JOIN_PRE);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getrightjoinipre", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents "is NULL" clause
* for this database
*/
public String getIsNull() {
String s = (String)dbMap.get(IS_NULL);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getisnull", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents "is not NULL" clause
* for this database
*/
public String getIsNotNull() {
String s = (String)dbMap.get(IS_NOT_NULL);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getisnotnull", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns true if this database need ansi style rtrim semantics.
*/
public boolean isAnsiTrim() {
String s = (String)dbMap.get(ANSI_TRIM);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isAnsiTrim", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns the string that represents "RTRIM" clause
* for this database
*/
public String getRtrim() {
String s = (String)dbMap.get(RTRIM);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getrtrim", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents postfix for "RTRIM" clause
* for this database
*/
public String getRtrimPost() {
String s = (String)dbMap.get(RTRIM_POST);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getrtrimpost", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents prefix for "Char_length" clause
* for this database
*/
public String getCharLength() {
String s = (String)dbMap.get(CHAR_LENGTH);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getcharlength", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents prefix for "Sqrt" clause
* for this database
*/
public String getSqrt() {
String s = (String)dbMap.get(SQRT);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"Sqrt"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getsqrt", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents prefix for "abs" clause
* for this database
*/
public String getAbs() {
String s = (String)dbMap.get(ABS);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"Abs"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getabs", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents "for update" clause
* for this database
*/
public String getForUpdate() {
String s = (String)dbMap.get(FOR_UPDATE);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getforupdate", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents start of table list
* for this database
*/
public String getTableListStart() {
String s = (String)dbMap.get(TABLE_LIST_START);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.gettableliststart", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents end of table list
* for this database
*/
public String getTableListEnd() {
String s = (String)dbMap.get(TABLE_LIST_END);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.gettablelistend", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents concatenation operation
* for this database
*/
public String getStringConcat() {
String s = (String)dbMap.get(STRING_CONCAT);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getstringconcat", s); // NOI18N
}
return SPACE + s + SPACE;
}
/**
* Returns the start identifier quote character for this database, or
* an empty string, if there is none.
*/
public String getQuoteCharStart() {
String s = (String)dbMap.get(QUOTE_CHAR_START);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getquotecharstart", s); // NOI18N
}
return s;
}
/**
* Returns the end identifier quote character for this database, or
* an empty string, if there is none.
*/
public String getQuoteCharEnd() {
String s = (String)dbMap.get(QUOTE_CHAR_END);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getquotecharend", s); // NOI18N
}
return s;
}
/**
* Returns true if only identifiers with special characters should be quoted
* for this database
*/
public boolean getQuoteSpecialOnly() {
String s = (String)dbMap.get(QUOTE_SPECIAL_ONLY);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getquotespecialonly", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns the string that represents prefix for "Substring" clause
* for this database
*/
public String getSubstring() {
String s = (String)dbMap.get(SUBSTRING);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"substring"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getsubstring", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents from part for "Substring" clause
* for this database
*/
public String getSubstringFrom() {
String s = (String)dbMap.get(SUBSTRING_FROM);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"from part of substring"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getsubstringfrom", s); // NOI18N
}
return SPACE + s + SPACE;
}
/**
* Returns the string that represents for part for "Substr" clause
* for this database
*/
public String getSubstringFor() {
String s = (String)dbMap.get(SUBSTRING_FOR);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"for part of substring"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getsubstringfor", s); // NOI18N
}
return SPACE + s + SPACE;
}
/**
* Returns the string that represents "Position" clause
* for this database
*/
public String getPosition() {
String s = (String)dbMap.get(POSITION);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"position"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getposition", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns the string that represents separator part of "Position" clause
* for this database
*/
public String getPositionSep() {
String s = (String)dbMap.get(POSITION_SEP);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
"in part of position"));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getpositionin", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns true if first position argument is Search String and second
* argument is Source String for this database
*/
public boolean isPositionSearchSource() {
String s = (String)dbMap.get(POSITION_SEARCH_SOURCE);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getpositionsrchsrc", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if position has three argument for this database
*/
public boolean isPositionThreeArgs() {
String s = (String)dbMap.get(POSITION_THREE_ARGS);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getposition3args", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if this database maps empty Strings to NULL
*/
public boolean mapEmptyStringToNull() {
String s = (String)dbMap.get(MAP_EMPTY_STRING_TO_NULL);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.mapemptystrtonull", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if this database supports "LIKE ESCAPE" clause
*/
public boolean supportsLikeEscape() {
String s = (String)dbMap.get(SUPPORTS_LIKE_ESCAPE);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.supportslikeescape", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns left string that represents "LIKE ESCAPE" clause
* for this database
*/
public String getLeftLikeEscape() {
String s = (String)dbMap.get(LEFT_LIKE_ESCAPE);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getleftlikeescape", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns right string that represents "LIKE ESCAPE" clause
* for this database
*/
public String getRightLikeEscape() {
String s = (String)dbMap.get(RIGHT_LIKE_ESCAPE);
if (s == null)
s = NONE;
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getrightlikeescape", s); // NOI18N
}
return SPACE + s;
}
/**
* Returns function name for comparing null value for this database
*/
public String getNullComparisonFunctionName() {
String s = (String)dbMap.get(NULL_COMPARISON_FUNCTION_NAME);
if (s == null)
s = NONE;
else
s = s.trim();
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getNullComparisonFunctionName", s); // NOI18N
}
return s;
}
/**
* Returns true if modulo operation uses function, false otherwise.
*/
public boolean isModOperationUsingFunction() {
return getModFunctionName().length() != 0;
}
/**
* Returns function name for MOD.
*/
public String getModFunctionName() {
String s = (String)dbMap.get(MOD_FUNCTION_NAME);
if (s == null) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.constraint.illegalop", // NOI18N
" % "));
}
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getModFunctionName", s); // NOI18N
}
return s;
}
/**
* Returns cast name that surrounds concat operation.
*/
public String getConcatCast() {
String s = (String)dbMap.get(CONCAT_CAST);
if (s == null)
s = NONE;
else
s = s.trim();
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getConcatCast", s); // NOI18N
}
return s;
}
/**
* Returns true if parameters need to be casted for this database
*/
public boolean isParameterCast() {
String s = (String)dbMap.get(PARAMETER_CAST);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isParameterCast", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns true if numeric parameters are inlined for this database
*/
public boolean isInlineNumeric() {
String s = (String)dbMap.get(INLINE_NUMERIC);
Boolean b = Boolean.valueOf(s);
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.isInlineNumeric", b); // NOI18N
}
return b.booleanValue();
}
/**
* Returns database vendor type
*/
public String getName() {
return vendorType;
}
/**
* Returns a SpecialDBOperation object
*/
public SpecialDBOperation getSpecialDBOperation() {
if (logger.isLoggable()) {
logger.fine("sqlstore.database.dbvendor.getSpecialDBOperation", specialDBOperation); // NOI18N
}
return specialDBOperation;
}
/**
* Gets string used as parameter marker. Parameters must be
* casted on DB2/Derby.
* @param type type for which parameter marker is required.
* @return parameter marker for <code>type</code>.
*/
public String getParameterMarker(int type) {
String paramMarker = "?"; // NOI18N
if (isParameterCast()) {
String castType = getCastType(type);
if (castType != null) {
paramMarker = "CAST (? AS " + castType + ")"; // NOI18N
}
}
return paramMarker;
}
/**
* Gets string used as parameter marker. Parameters must be
* casted on DB2/Derby. The cast type should match the actual
* JDBC call used to bind the parameter.
* @param type type for which cast type is required.
* @return String used as cast type for input type.
* <code>null</code> if cast type is not required.
*/
private static String getCastType(int type) {
//
//DB2type length(bits) JavaType
//----------------------------------------------
//SMALLINT 16 boolean, byte, short
//INTEGER 32 int, char(16 bit unsigned)
//BIGINT 64 long
//REAL 32 float
//DOUBLE 64 double
//
String castType = null;
switch(type) {
case FieldTypeEnumeration.BOOLEAN_PRIMITIVE :
case FieldTypeEnumeration.BOOLEAN :
castType = "SMALLINT";
break;
// CHARACTER_PRIMITIVE and CHARACTER are bound
// to a PreparedStatement as String.
case FieldTypeEnumeration.CHARACTER_PRIMITIVE :
case FieldTypeEnumeration.CHARACTER :
case FieldTypeEnumeration.STRING :
castType = "VARCHAR(32672)"; //Max length of varchar col on DB2
break;
case FieldTypeEnumeration.BYTE_PRIMITIVE :
case FieldTypeEnumeration.BYTE :
castType = "SMALLINT";
break;
case FieldTypeEnumeration.SHORT_PRIMITIVE :
case FieldTypeEnumeration.SHORT :
castType = "SMALLINT";
break;
case FieldTypeEnumeration.INTEGER_PRIMITIVE :
case FieldTypeEnumeration.INTEGER :
castType = "INTEGER";
break;
case FieldTypeEnumeration.LONG_PRIMITIVE :
case FieldTypeEnumeration.LONG :
castType = "BIGINT";
break;
case FieldTypeEnumeration.FLOAT_PRIMITIVE :
case FieldTypeEnumeration.FLOAT :
castType = "REAL";
break;
case FieldTypeEnumeration.DOUBLE_PRIMITIVE :
case FieldTypeEnumeration.DOUBLE :
castType = "DOUBLE";
break;
/* Decide on what should this be casted to ?
case FieldTypeEnumeration.ENUMTYPE_BIGDECIMAL :
case FieldTypeEnumeration.ENUMTYPE_BIGINTEGER :
break;
*/
case FieldTypeEnumeration.UTIL_DATE :
case FieldTypeEnumeration.SQL_TIMESTAMP :
castType = "TIMESTAMP";
break;
case FieldTypeEnumeration.SQL_DATE :
castType = "DATE";
break;
case FieldTypeEnumeration.SQL_TIME :
castType = "TIME";
break;
}
return castType;
}
}