// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dq.dbms;
import java.sql.SQLException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.talend.core.model.metadata.builder.connection.Connection;
import org.talend.core.model.metadata.builder.database.dburl.SupportDBUrlStore;
import org.talend.core.model.metadata.builder.database.dburl.SupportDBUrlType;
import org.talend.cwm.db.connection.ConnectionUtils;
import org.talend.cwm.helper.ConnectionHelper;
import org.talend.cwm.helper.SwitchHelpers;
import org.talend.cwm.helper.TaggedValueHelper;
import org.talend.cwm.management.i18n.Messages;
import org.talend.dataquality.PluginConstant;
import org.talend.dataquality.analysis.Analysis;
import org.talend.dataquality.analysis.AnalysisContext;
import org.talend.dataquality.analysis.ExecutionLanguage;
import org.talend.utils.ProductVersion;
import orgomg.cwm.foundation.softwaredeployment.DataManager;
import orgomg.cwm.foundation.softwaredeployment.SoftwareSystem;
/**
* @author scorreia
*
* Factory for the creation of DbmsLanguage objects.
*/
public final class DbmsLanguageFactory {
private static Logger log = Logger.getLogger(DbmsLanguageFactory.class);
private DbmsLanguageFactory() {
// avoid instantiation
}
/**
* Method "createDbmsLanguage".
*
* @param dataManager a data manager used for initializing the correct language in the created DbmsLanguage
* @return a new DbmsLanguage even if the data manager did not allow to get the correct language
*/
public static DbmsLanguage createDbmsLanguage(DataManager dataManager, ExecutionLanguage... exeLanguage) {
if (exeLanguage.length > 0 && exeLanguage[0] == ExecutionLanguage.JAVA) {
return createDbmsLanguage(SupportDBUrlType.JAVADEFAULTURL);
}
DbmsLanguage dbmsLanguage = new DbmsLanguage();
if (dataManager == null) {
return dbmsLanguage;
}
Connection dataprovider = SwitchHelpers.CONNECTION_SWITCH.doSwitch(dataManager);
if (dataprovider == null) {
return dbmsLanguage;
}
// MOD sizhaoliu TDQ-6316 deprecate software system
// TdSoftwareSystem softwareSystem = SoftwareSystemManager.getInstance().getSoftwareSystem(dataprovider);
// MOD qiongli 2011-1-11 feature 16796.handle the delimited file
boolean isDelimitedFile = ConnectionUtils.isDelimitedFileConnection(dataprovider);
if (isDelimitedFile) {
dbmsLanguage = createDbmsLanguage(DbmsLanguage.DELIMITEDFILE, PluginConstant.EMPTY_STRING);
} else if (dataprovider != null) {
String productSubtype = TaggedValueHelper.getValueString(TaggedValueHelper.DB_PRODUCT_NAME, dataprovider);
// Added 20130222 TDQ-6760 yyin, if the tag value is null, update it
// All analysis & reports will go here, so check it here is better than other place.
if (StringUtils.isBlank(productSubtype)) {
ConnectionUtils.updataTaggedValueForConnectionItem(dataprovider);
productSubtype = TaggedValueHelper.getValueString(TaggedValueHelper.DB_PRODUCT_NAME, dataprovider);
}
// ~
String productVersion = TaggedValueHelper.getValueString(TaggedValueHelper.DB_PRODUCT_VERSION, dataprovider);
if (log.isDebugEnabled()) {
log.debug("Software system subtype (Database type): " + productSubtype); //$NON-NLS-1$
}
if (StringUtils.isNotBlank(productSubtype)) {
dbmsLanguage = createDbmsLanguage(productSubtype, productVersion);
}
}
String identifierQuoteString = ConnectionHelper.getIdentifierQuoteString(dataprovider);
if (identifierQuoteString == null || identifierQuoteString.length() == 0) {
// MOD scorreia 2009-11-24 check for null because in some cases (DB2 z/OS and TOP 3.2.2), the identifier
// quote was stored as null.
// given data provider has not stored the identifier quote (version 1.1.0 of TOP)
// we must set it by hand
identifierQuoteString = dbmsLanguage.getHardCodedQuoteIdentifier();
}
dbmsLanguage.setDbQuoteString(identifierQuoteString);
return dbmsLanguage;
}
/**
* Method "createDbmsLanguage".
*
* @param dbmsSubtype
* @return the appropriate DbmsLanguage
*/
public static DbmsLanguage createDbmsLanguage(String dbmsSubtype, String databaseVersion) {
// TODO find an appropriate place to set the database version (e.g for hive embedded)
String dbVersionStr = databaseVersion;
if (dbVersionStr == null) {
dbVersionStr = "0.0.0"; //$NON-NLS-1$
}
ProductVersion dbVersion = ProductVersion.fromString(dbVersionStr, true);
DbmsLanguage dbmsLanguage = null;
if (isMySQL(dbmsSubtype)) {
dbmsLanguage = new MySQLDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isOracle(dbmsSubtype)) {
dbmsLanguage = new OracleDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isDB2(dbmsSubtype)) {
dbmsLanguage = new DB2DbmsLanguage(dbmsSubtype, dbVersion);
} else if (isAS400(dbmsSubtype)) {
dbmsLanguage = new AS400DbmsLanguage(dbmsSubtype, dbVersion);
} else if (isMSSQL(dbmsSubtype)) {
dbmsLanguage = new MSSqlDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isPostgresql(dbmsSubtype)) {
dbmsLanguage = new PostgresqlDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isRedshift(dbmsSubtype)) {
dbmsLanguage = new RedshiftDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isExasol(dbmsSubtype)) {
dbmsLanguage = new ExasolDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isSybase(dbmsSubtype)) {
dbmsLanguage = new SybaseASEDbmsLanguage(dbVersion);
} else if (isSQLite(dbmsSubtype)) {
dbmsLanguage = new SQLiteDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isTeradata(dbmsSubtype)) {
dbmsLanguage = new TeradataDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isIngres(dbmsSubtype)) {
dbmsLanguage = new IngresDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isDelimitedFile(dbmsSubtype)) {
dbmsLanguage = new DelimitedFileLanguage(dbmsSubtype, dbVersion);
} else if (isInfomix(dbmsSubtype)) {
// MOD zshen fixed bug 11005: SQL syntax error for all analysis on Informix databases in Talend Open
// Profiler
dbmsLanguage = new InfomixDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isHive(dbmsSubtype) || isImpala(dbmsSubtype)) {
dbmsLanguage = new HiveDbmsLanguage(DbmsLanguage.HIVE, dbVersion);
} else if (isVertica(dbmsSubtype)) {
dbmsLanguage = new VerticaDbmsLanguage(dbmsSubtype, dbVersion);
} else if (isNetezza(dbmsSubtype)) {
dbmsLanguage = new NetezzaDbmsLanguage(dbmsSubtype, dbVersion);
} else {
dbmsLanguage = new DbmsLanguage(dbmsSubtype, dbVersion);
}
if (PluginConstant.EMPTY_STRING.equals(dbmsLanguage.getDbQuoteString())) {
dbmsLanguage.setDbQuoteString(dbmsLanguage.getHardCodedQuoteIdentifier());
}
return dbmsLanguage;
}
/**
* DOC talend Comment method "isImpala".
*
* @param dbmsSubtype
* @return
*/
private static boolean isImpala(String dbmsSubtype) {
return DbmsLanguage.IMPALA.equalsIgnoreCase(dbmsSubtype);
}
public static DbmsLanguage createDbmsLanguage(String dataType) {
SupportDBUrlType dbType = SupportDBUrlStore.getInstance().getDBUrlType(dataType);
return createDbmsLanguage(dbType);
}
/**
* DOC jet Comment method "getDbmsLanguage".
*
* @param dbType
* @return
*/
public static DbmsLanguage createDbmsLanguage(SupportDBUrlType dbType) {
DbmsLanguage result = null;
if (dbType == null) {
return new DbmsLanguage();
}
// MOD qiongli 2011-4-18 bug 16723,data cleansing
result = createDbmsLanguage(dbType.getLanguage(), PluginConstant.EMPTY_STRING);
return result;
}
/**
* Method "createDbmsLanguage".
*
* @param connection a connection (must be open)
* @return the appropriate DbmsLanguage or a default one if something failed with the connection.
*/
@SuppressWarnings("deprecation")
public static DbmsLanguage createDbmsLanguage(java.sql.Connection connection) {
assert connection != null;
// MOD xqliu 2009-07-13 bug 7888
String databaseProductName = null;
try {
databaseProductName = org.talend.utils.sql.ConnectionUtils.getConnectionMetadata(connection).getDatabaseProductName();
databaseProductName = databaseProductName == null ? PluginConstant.EMPTY_STRING : databaseProductName;
String databaseProductVersion = null;
try {
databaseProductVersion = org.talend.utils.sql.ConnectionUtils.getConnectionMetadata(connection)
.getDatabaseProductVersion();
databaseProductVersion = databaseProductVersion == null ? "0" : databaseProductVersion; //$NON-NLS-1$
} catch (Exception e) {
log.warn(Messages.getString("DbmsLanguageFactory.RetrieveVerSionException", databaseProductName), e);//$NON-NLS-1$
}
DbmsLanguage dbmsLanguage = createDbmsLanguage(databaseProductName, databaseProductVersion);
dbmsLanguage.setDbQuoteString(org.talend.utils.sql.ConnectionUtils.getConnectionMetadata(connection)
.getIdentifierQuoteString());
return dbmsLanguage;
} catch (SQLException e) {
log.warn(Messages.getString("DbmsLanguageFactory.RetrieveInfoException", e), e);//$NON-NLS-1$
return new DbmsLanguage();
}
}
private static boolean isMySQL(String dbms) {
return compareDbmsLanguage(DbmsLanguage.MYSQL, dbms);
}
public static boolean isOracle(String dbms) {
return compareDbmsLanguage(DbmsLanguage.ORACLE, dbms);
}
private static boolean isPostgresql(String dbms) {
return compareDbmsLanguage(DbmsLanguage.POSTGRESQL, dbms);
}
private static boolean isMSSQL(String dbms) {
return compareDbmsLanguage(DbmsLanguage.MSSQL, dbms);
}
private static boolean isDB2(String dbms) {
return compareDbmsLanguage(DbmsLanguage.DB2, dbms);
}
private static boolean isAS400(String dbms) {
return compareDbmsLanguage(DbmsLanguage.AS400, dbms);
}
private static boolean isSybase(String dbms) {
return ConnectionUtils.isSybaseeDBProducts(dbms);
}
private static boolean isSQLite(String dbms) {
return compareDbmsLanguage(DbmsLanguage.SQLITE3, dbms);
}
private static boolean isTeradata(String dbms) {
return compareDbmsLanguage(DbmsLanguage.TERADATA, dbms);
}
private static boolean isIngres(String dbms) {
return compareDbmsLanguage(DbmsLanguage.INGRES, dbms);
}
private static boolean isDelimitedFile(String dbms) {
return compareDbmsLanguage(DbmsLanguage.DELIMITEDFILE, dbms);
}
// MOD zshen 11005: SQL syntax error for all analysis on Informix databases in Talend Open Profiler
public static boolean isInfomix(String dbms) {
return compareDbmsLanguage(DbmsLanguage.INFOMIX, dbms);
}
public static boolean isHive(String dbms) {
return compareDbmsLanguage(DbmsLanguage.HIVE, dbms);
}
public static boolean isVertica(String dbms) {
return compareDbmsLanguage(DbmsLanguage.VERTICA, dbms);
}
public static boolean isRedshift(String dbms) {
return compareDbmsLanguage(DbmsLanguage.REDSHIFT, dbms);
}
public static boolean isExasol(String dbms) {
return compareDbmsLanguage(DbmsLanguage.EXASOLUTION, dbms);
}
private static boolean isNetezza(String dbms) {
return compareDbmsLanguage(DbmsLanguage.NETEZZA, dbms);
}
public static boolean isAllDatabaseType(String dbms) {
return compareDbmsLanguage(DbmsLanguage.SQL, dbms);
}
/**
* if lang1 equals lang2 (ignore case) return true, else return false.
*
* @param lang1
* @param lang2
* @return
*/
public static boolean equalsDbmsLanguage(String lang1, String lang2) {
if (lang1 == null || lang2 == null) {
return false;
}
return StringUtils.equalsIgnoreCase(lang1, lang2);
}
public static boolean compareDbmsLanguage(String lang1, String lang2) {
if (lang1 == null || lang2 == null) {
return false;
}
// When source language is defaule or target language is default they are must equals between lang1 and lang2,
// else will cause of error mapping.
// For example default will mapping MySQL, PostgreSQL,Microsoft SQL Server
if (StringUtils.equalsIgnoreCase(lang1, DbmsLanguage.SQL) || StringUtils.equalsIgnoreCase(lang2, DbmsLanguage.SQL)) {
return StringUtils.equalsIgnoreCase(lang1, lang2);
}
// MOD xqliu 2011-12-20 TDQ-4232, FOR AS400
if (StringUtils.contains(lang1, DbmsLanguage.AS400) && StringUtils.contains(lang2, DbmsLanguage.AS400)) {
return true;
}
if (StringUtils.contains(lang1, DbmsLanguage.AS400) && !StringUtils.contains(lang2, DbmsLanguage.AS400)) {
return false;
}
if (!StringUtils.contains(lang1, DbmsLanguage.AS400) && StringUtils.contains(lang2, DbmsLanguage.AS400)) {
return false;
}
// ~ TDQ-4232
// MOD mzhao 2010-08-02 bug 14464, for AS400
if (StringUtils.contains(lang1, DbmsLanguage.AS400) && StringUtils.contains(StringUtils.upperCase(lang2), lang1)) {
return true;
}
// MOD 2008-08-04 scorreia: for DB2 database, dbName can be "DB2/NT" or "DB2/6000" or "DB2"...
if (lang1.startsWith(DbmsLanguage.DB2)) {
if (StringUtils.contains(lang2, DbmsLanguage.AS400)) {
return false;
}
return StringUtils.upperCase(lang1).startsWith(StringUtils.upperCase(lang2))
|| StringUtils.upperCase(lang2).startsWith(StringUtils.upperCase(lang1));
} else
// MOD 2010-01-26 zshen: for informix database, dbName can be "informix" or "informix Dynamic Server"
if (lang1.startsWith(DbmsLanguage.INFOMIX)) {
return StringUtils.upperCase(lang1).startsWith(StringUtils.upperCase(lang2))
|| StringUtils.upperCase(lang2).startsWith(StringUtils.upperCase(lang1));
}
if (StringUtils.contains(lang1, DbmsLanguage.VERTICA) && StringUtils.contains(lang2, DbmsLanguage.VERTICA)) {
return true;
}
// MOD 2014-02-10 for TDQ-8600 Column Analysis fails with Netezza
if (StringUtils.contains(lang1, DbmsLanguage.NETEZZA) && StringUtils.contains(lang2, DbmsLanguage.NETEZZA)) {
return true;
}
// MOD 2014-02-27 for TDQ-8601
if (StringUtils.contains(lang1, DbmsLanguage.HIVE) && StringUtils.contains(lang2, DbmsLanguage.HIVE)) {
return true;
}
return StringUtils.contains(StringUtils.upperCase(lang1), StringUtils.upperCase(lang2))
|| StringUtils.contains(StringUtils.upperCase(lang2), StringUtils.upperCase(lang1));
}
/**
* Method "createDbmsLanguage".
*
* @param analysis
* @return the dbms language associated to the connection of the given analysis or a default one.
*/
public static DbmsLanguage createDbmsLanguage(Analysis analysis, ExecutionLanguage... exeLanguage) {
final AnalysisContext context = analysis.getContext();
ExecutionLanguage theLanguage = null;
if (exeLanguage != null && exeLanguage.length > 0) {
theLanguage = exeLanguage[0];
} else {
theLanguage = analysis.getParameters().getExecutionLanguage();
}
if (theLanguage == ExecutionLanguage.JAVA) {
return createDbmsLanguage(SupportDBUrlType.JAVADEFAULTURL);
}
if (context != null) {
final DataManager dm = context.getConnection();
if (dm != null) {
return createDbmsLanguage(dm);
}
}
return new DbmsLanguage();
}
@Deprecated
public static DbmsLanguage createDbmsLanguage(SoftwareSystem softwareSystem) {
if (softwareSystem != null) {
return createDbmsLanguage(softwareSystem.getName(), softwareSystem.getVersion());
}
return new DbmsLanguage();
}
}