/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved. */ package org.pentaho.di.trans.steps.gpload; import java.util.List; import org.pentaho.di.core.CheckResult; import org.pentaho.di.core.CheckResultInterface; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.SQLStatement; import org.pentaho.di.core.annotations.Step; import org.pentaho.di.core.database.Database; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleStepException; import org.pentaho.di.core.exception.KettleXMLException; import org.pentaho.di.core.injection.Injection; import org.pentaho.di.core.injection.InjectionSupported; import org.pentaho.di.core.row.RowMeta; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.variables.VariableSpace; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.ObjectId; import org.pentaho.di.repository.Repository; import org.pentaho.di.shared.SharedObjectInterface; import org.pentaho.di.trans.DatabaseImpact; import org.pentaho.di.trans.Trans; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.StepDataInterface; import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; import org.pentaho.metastore.api.IMetaStore; import org.w3c.dom.Node; /** * GPLoad Bulk Loader Step Meta * * @author Matt Casters, Sean Flatley */ @Step( id = "GPLoad", image = "BLKGP.svg", i18nPackageName = "org.pentaho.di.trans.steps.gpload", name = "GPLoad.TypeLongDesc", description = "GPLoad.TypeLongDesc", categoryDescription = "i18n:org.pentaho.di.trans.step:BaseStep.Category.Bulk", documentationUrl = "http://wiki.pentaho.com/display/EAI/Greenplum+Load" ) @InjectionSupported( localizationPrefix = "GPLoad.Injection.", groups = { "FIELDS", "LOCALHOSTS", "GP_CONFIG" } ) public class GPLoadMeta extends BaseStepMeta implements StepMetaInterface { private static Class<?> PKG = GPLoadMeta.class; // for i18n purposes, needed by Translator2!! /** Collection of Local hosts **/ @Injection( name = "LOCALHOST_NAME", group = "LOCALHOSTS" ) private String[] localHosts; /** LocalHostPort **/ @Injection( name = "PORT", group = "LOCALHOSTS" ) private String localhostPort; /** what's the schema for the target? */ @Injection( name = "SCHEMA_NAME" ) private String schemaName; /** what's the table for the target? */ @Injection( name = "TABLE_NAME" ) private String tableName; /** what's the target of the error table? */ @Injection( name = "ERROR_TABLE", group = "GP_CONFIG" ) private String errorTableName; /** Path to the gpload utility */ @Injection( name = "GPLOAD_PATH", group = "GP_CONFIG" ) private String gploadPath; /** Path to the control file */ @Injection( name = "CONTROL_FILE", group = "GP_CONFIG" ) private String controlFile; /** Path to the data file */ @Injection( name = "DATA_FILE", group = "GP_CONFIG" ) private String dataFile; /** Path to the log file */ @Injection( name = "LOG_FILE", group = "GP_CONFIG" ) private String logFile; /** NULL_AS parameter for gpload - gpload treats values matching this string as null */ @Injection( name = "NULL_AS", group = "GP_CONFIG" ) private String nullAs; /** database connection */ private DatabaseMeta databaseMeta; /** Specified database field */ @Injection( name = "FIELD_TABLE", group = "FIELDS" ) private String[] fieldTable; /** Field name in the stream */ @Injection( name = "FIELD_STREAM", group = "FIELDS" ) private String[] fieldStream; /** Database column to match on for an update or merge operation */ @Injection( name = "FIELD_MATCH", group = "FIELDS" ) private boolean[] matchColumn; /** Database columns to update */ @Injection( name = "FIELD_UPDATE", group = "FIELDS" ) private boolean[] updateColumn; /** the date mask to use if the value is a date */ @Injection( name = "FIELD_DATEMASK", group = "FIELDS" ) private String[] dateMask; /** maximum errors */ @Injection( name = "MAX_ERRORS", group = "GP_CONFIG" ) private String maxErrors; /** Load method */ @Injection( name = "LOAD_METHOD" ) private String loadMethod; /** Load action */ @Injection( name = "LOAD_ACTION", group = "FIELDS" ) private String loadAction; /** Encoding to use */ @Injection( name = "ENCODING", group = "GP_CONFIG" ) private String encoding; /** Erase files after use */ @Injection( name = "ERASE_FILE" ) private boolean eraseFiles; /** Boolean to indicate that numbers are to be enclosed */ @Injection( name = "ENCLOSURE_NUMBERS" ) private boolean encloseNumbers; /** Data file delimiter */ @Injection( name = "DELIMITER", group = "GP_CONFIG" ) private String delimiter; /** Default number of maximum errors allowed on a load */ public static String MAX_ERRORS_DEFAULT = "50"; /** Update condition **/ @Injection( name = "UPDATE_CONDITIONS", group = "FIELDS" ) private String updateCondition; /* * Encodings supported by GPLoad. This list was obtained from the GPAAdminGuide. */ public static final String[] SUPPORTED_ENCODINGS = { "", "BIG5", "EUC_CN", "EUC_JP", "EUC_KR", "EUC_TW", "GB18030", "GBK", "ISO-8859-1", "ISO_8859_5", "ISO_8859_6", "ISO_8859_7", "ISO_8859_8", "JOHAB", "KOI8", "LATIN1", "LATIN2", "LATIN3", "LATIN4", "LATIN5", "LATIN6", "LATIN7", "LATIN8", "LATIN9", "LATIN10", "MULE_INTERNAL", "SJIS", "SQL_ASCII", "UHC", "UTF8", "WIN866", "WIN874", "WIN1250", "WIN1251", "WIN1252", "WIN1253", "WIN1254", "WIN1255", "WIN1256", "WIN1257", "WIN1258" }; /* * Do not translate following values!!! They are will end up in the job export. */ public static final String ACTION_INSERT = "insert"; public static final String ACTION_UPDATE = "update"; public static final String ACTION_MERGE = "merge"; /* * Do not translate following values!!! They are will end up in the job export. */ // final static public String METHOD_AUTO_CONCURRENT = "AUTO_CONCURRENT"; public static final String METHOD_AUTO_END = "AUTO_END"; public static final String METHOD_MANUAL = "MANUAL"; /* * Do not translate following values!!! They are will end up in the job export. */ public static final String DATE_MASK_DATE = "DATE"; public static final String DATE_MASK_DATETIME = "DATETIME"; public GPLoadMeta() { super(); } /** * @return Returns the database. */ public DatabaseMeta getDatabaseMeta() { return databaseMeta; } /** * @param database * The database to set. */ public void setDatabaseMeta( DatabaseMeta database ) { this.databaseMeta = database; } /** * @return Returns the tableName. */ public String getTableName() { return tableName; } /** * @param tableName * The tableName to set. */ public void setTableName( String tableName ) { this.tableName = tableName; } /** * @return Returns the errorTableName. */ public String getErrorTableName() { return errorTableName; } /** * @param errorTableName * The error table name to set. */ public void setErrorTableName( String errorTableName ) { this.errorTableName = errorTableName; } public String getGploadPath() { return gploadPath; } public void setGploadPath( String gploadPath ) { this.gploadPath = gploadPath; } /** * @return Returns the fieldTable. */ public String[] getFieldTable() { return fieldTable; } /** * @param fieldTable * The fieldTable to set. */ public void setFieldTable( String[] fieldTable ) { this.fieldTable = fieldTable; } /** * @return Returns the fieldStream. */ public String[] getFieldStream() { return fieldStream; } /** * @param fieldStream * The fieldStream to set. */ public void setFieldStream( String[] fieldStream ) { this.fieldStream = fieldStream; } public String[] getDateMask() { return dateMask; } public void setDateMask( String[] dateMask ) { this.dateMask = dateMask; } public void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ) throws KettleXMLException { readData( stepnode, databases ); } public void allocate( int nrvalues ) { fieldTable = new String[nrvalues]; fieldStream = new String[nrvalues]; dateMask = new String[nrvalues]; matchColumn = new boolean[nrvalues]; updateColumn = new boolean[nrvalues]; } public void allocateLocalHosts( int numberOfLocalHosts ) { this.localHosts = new String[numberOfLocalHosts]; } public Object clone() { GPLoadMeta retval = (GPLoadMeta) super.clone(); int nrvalues = fieldTable.length; retval.allocate( nrvalues ); for ( int i = 0; i < nrvalues; i++ ) { retval.fieldTable[i] = fieldTable[i]; retval.fieldStream[i] = fieldStream[i]; retval.dateMask[i] = dateMask[i]; retval.matchColumn[i] = matchColumn[i]; retval.updateColumn[i] = updateColumn[i]; } return retval; } private void readData( Node stepnode, List<? extends SharedObjectInterface> databases ) throws KettleXMLException { try { String con = XMLHandler.getTagValue( stepnode, "connection" ); databaseMeta = DatabaseMeta.findDatabase( databases, con ); maxErrors = XMLHandler.getTagValue( stepnode, "errors" ); schemaName = XMLHandler.getTagValue( stepnode, "schema" ); tableName = XMLHandler.getTagValue( stepnode, "table" ); errorTableName = XMLHandler.getTagValue( stepnode, "error_table" ); loadMethod = XMLHandler.getTagValue( stepnode, "load_method" ); loadAction = XMLHandler.getTagValue( stepnode, "load_action" ); gploadPath = XMLHandler.getTagValue( stepnode, "gpload_path" ); controlFile = XMLHandler.getTagValue( stepnode, "control_file" ); dataFile = XMLHandler.getTagValue( stepnode, "data_file" ); delimiter = XMLHandler.getTagValue( stepnode, "delimiter" ); logFile = XMLHandler.getTagValue( stepnode, "log_file" ); nullAs = XMLHandler.getTagValue( stepnode, "null_as" ); eraseFiles = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "erase_files" ) ); encoding = XMLHandler.getTagValue( stepnode, "encoding" ); updateCondition = XMLHandler.getTagValue( stepnode, "update_condition" ); Node localHostsNode = XMLHandler.getSubNode( stepnode, "local_hosts" ); int nLocalHosts = XMLHandler.countNodes( localHostsNode, "local_host" ); allocateLocalHosts( nLocalHosts ); for ( int i = 0; i < nLocalHosts; i++ ) { Node localHostNode = XMLHandler.getSubNodeByNr( localHostsNode, "local_host", i ); localHosts[i] = XMLHandler.getNodeValue( localHostNode ); } localhostPort = XMLHandler.getTagValue( stepnode, "localhost_port" ); encloseNumbers = XMLHandler.getTagValue( stepnode, "enclose_numbers" ).equalsIgnoreCase( "Y" ); int nrvalues = XMLHandler.countNodes( stepnode, "mapping" ); allocate( nrvalues ); for ( int i = 0; i < nrvalues; i++ ) { Node vnode = XMLHandler.getSubNodeByNr( stepnode, "mapping", i ); fieldTable[i] = XMLHandler.getTagValue( vnode, "stream_name" ); fieldStream[i] = XMLHandler.getTagValue( vnode, "field_name" ); if ( fieldStream[i] == null ) { fieldStream[i] = fieldTable[i]; // default: the same name! } String locDateMask = XMLHandler.getTagValue( vnode, "date_mask" ); if ( locDateMask == null ) { dateMask[i] = ""; } else { if ( GPLoadMeta.DATE_MASK_DATE.equals( locDateMask ) || GPLoadMeta.DATE_MASK_DATETIME.equals( locDateMask ) ) { dateMask[i] = locDateMask; } else { dateMask[i] = ""; } } matchColumn[i] = ( "Y".equalsIgnoreCase( XMLHandler.getTagValue( vnode, "match_column" ) ) ); updateColumn[i] = ( "Y".equalsIgnoreCase( XMLHandler.getTagValue( vnode, "update_column" ) ) ); } } catch ( Exception e ) { throw new KettleXMLException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.UnableToReadStepInfoFromXML" ), e ); } } public void setDefault() { // TODO: Make non empty defaults public static Strings fieldTable = null; databaseMeta = null; maxErrors = GPLoadMeta.MAX_ERRORS_DEFAULT; schemaName = ""; localhostPort = ""; tableName = BaseMessages.getString( PKG, "GPLoadMeta.DefaultTableName" ); errorTableName = ""; // BaseMessages.getString(PKG, "GPLocal.ErrorTable.Prefix")+tableName; loadMethod = METHOD_AUTO_END; loadAction = ACTION_INSERT; gploadPath = "/usr/local/greenplum-db/bin/gpload"; controlFile = "control${Internal.Step.CopyNr}.cfg"; dataFile = "load${Internal.Step.CopyNr}.dat"; logFile = ""; nullAs = ""; encoding = ""; delimiter = ","; encloseNumbers = false; eraseFiles = true; updateCondition = ""; allocate( 0 ); allocateLocalHosts( 0 ); } public String getXML() { StringBuffer retval = new StringBuffer( 300 ); retval.append( " " ).append( XMLHandler.addTagValue( "connection", databaseMeta == null ? "" : databaseMeta.getName() ) ); retval.append( " " ).append( XMLHandler.addTagValue( "errors", maxErrors ) ); retval.append( " " ).append( XMLHandler.addTagValue( "schema", schemaName ) ); retval.append( " " ).append( XMLHandler.addTagValue( "table", tableName ) ); retval.append( " " ).append( XMLHandler.addTagValue( "error_table", errorTableName ) ); retval.append( " " ).append( XMLHandler.addTagValue( "load_method", loadMethod ) ); retval.append( " " ).append( XMLHandler.addTagValue( "load_action", loadAction ) ); retval.append( " " ).append( XMLHandler.addTagValue( "gpload_path", gploadPath ) ); retval.append( " " ).append( XMLHandler.addTagValue( "control_file", controlFile ) ); retval.append( " " ).append( XMLHandler.addTagValue( "data_file", dataFile ) ); retval.append( " " ).append( XMLHandler.addTagValue( "delimiter", delimiter ) ); retval.append( " " ).append( XMLHandler.addTagValue( "log_file", logFile ) ); retval.append( " " ).append( XMLHandler.addTagValue( "null_as", nullAs ) ); retval.append( " " ).append( XMLHandler.addTagValue( "erase_files", eraseFiles ) ); retval.append( " " ).append( XMLHandler.addTagValue( "encoding", encoding ) ); retval.append( " " ).append( XMLHandler.addTagValue( "enclose_numbers", ( encloseNumbers ? "Y" : "N" ) ) ); retval.append( " " ).append( XMLHandler.addTagValue( "localhost_port", localhostPort ) ); retval.append( " " ).append( XMLHandler.addTagValue( "update_condition", updateCondition ) ); for ( int i = 0; i < fieldTable.length; i++ ) { retval.append( " <mapping>" ).append( Const.CR ); retval.append( " " ).append( XMLHandler.addTagValue( "stream_name", fieldTable[i] ) ); retval.append( " " ).append( XMLHandler.addTagValue( "field_name", fieldStream[i] ) ); retval.append( " " ).append( XMLHandler.addTagValue( "date_mask", dateMask[i] ) ); retval.append( " " ).append( XMLHandler.addTagValue( "match_column", ( matchColumn[i] ? "Y" : "N" ) ) ); retval.append( " " ).append( XMLHandler.addTagValue( "update_column", ( updateColumn[i] ? "Y" : "N" ) ) ); retval.append( " </mapping>" ).append( Const.CR ); } retval.append( " <local_hosts>" ).append( Const.CR ); for ( String localHost : localHosts ) { retval.append( " " ).append( XMLHandler.addTagValue( "local_host", localHost ) ); } retval.append( " </local_hosts>" ).append( Const.CR ); return retval.toString(); } public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException { try { databaseMeta = rep.loadDatabaseMetaFromStepAttribute( id_step, "id_connection", databases ); maxErrors = rep.getStepAttributeString( id_step, "errors" ); schemaName = rep.getStepAttributeString( id_step, "schema" ); tableName = rep.getStepAttributeString( id_step, "table" ); errorTableName = rep.getStepAttributeString( id_step, "error_table" ); loadMethod = rep.getStepAttributeString( id_step, "load_method" ); loadAction = rep.getStepAttributeString( id_step, "load_action" ); gploadPath = rep.getStepAttributeString( id_step, "gpload_path" ); controlFile = rep.getStepAttributeString( id_step, "control_file" ); dataFile = rep.getStepAttributeString( id_step, "data_file" ); delimiter = rep.getStepAttributeString( id_step, "delimiter" ); logFile = rep.getStepAttributeString( id_step, "log_file" ); nullAs = rep.getStepAttributeString( id_step, "null_as" ); eraseFiles = rep.getStepAttributeBoolean( id_step, "erase_files" ); encoding = rep.getStepAttributeString( id_step, "encoding" ); localhostPort = rep.getStepAttributeString( id_step, "localhost_port" ); encloseNumbers = ( rep.getStepAttributeString( id_step, "enclose_numbers" ).equalsIgnoreCase( "Y" ) ? true : false ); updateCondition = rep.getStepAttributeString( id_step, "update_condition" ); int numberOfLocalHosts = rep.countNrStepAttributes( id_step, "local_host" ); allocateLocalHosts( numberOfLocalHosts ); for ( int i = 0; i < numberOfLocalHosts; i++ ) { localHosts[i] = rep.getStepAttributeString( id_step, i, "local_host" ); } int nrvalues = rep.countNrStepAttributes( id_step, "stream_name" ); allocate( nrvalues ); for ( int i = 0; i < nrvalues; i++ ) { fieldTable[i] = rep.getStepAttributeString( id_step, i, "stream_name" ); fieldStream[i] = rep.getStepAttributeString( id_step, i, "field_name" ); dateMask[i] = rep.getStepAttributeString( id_step, i, "date_mask" ); matchColumn[i] = rep.getStepAttributeBoolean( id_step, i, "match_column" ); updateColumn[i] = rep.getStepAttributeBoolean( id_step, i, "update_column" ); } } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.UnexpectedErrorReadingStepInfoFromRepository" ), e ); } } public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ) throws KettleException { try { rep.saveDatabaseMetaStepAttribute( id_transformation, id_step, "id_connection", databaseMeta ); rep.saveStepAttribute( id_transformation, id_step, "errors", maxErrors ); rep.saveStepAttribute( id_transformation, id_step, "schema", schemaName ); rep.saveStepAttribute( id_transformation, id_step, "table", tableName ); rep.saveStepAttribute( id_transformation, id_step, "error_table", errorTableName ); rep.saveStepAttribute( id_transformation, id_step, "load_method", loadMethod ); rep.saveStepAttribute( id_transformation, id_step, "load_action", loadAction ); rep.saveStepAttribute( id_transformation, id_step, "gpload_path", gploadPath ); rep.saveStepAttribute( id_transformation, id_step, "control_file", controlFile ); rep.saveStepAttribute( id_transformation, id_step, "data_file", dataFile ); rep.saveStepAttribute( id_transformation, id_step, "delimiter", delimiter ); rep.saveStepAttribute( id_transformation, id_step, "log_file", logFile ); rep.saveStepAttribute( id_transformation, id_step, "null_as", nullAs ); rep.saveStepAttribute( id_transformation, id_step, "erase_files", eraseFiles ); rep.saveStepAttribute( id_transformation, id_step, "encoding", encoding ); rep.saveStepAttribute( id_transformation, id_step, "enclose_numbers", ( encloseNumbers ? "Y" : "N" ) ); rep.saveStepAttribute( id_transformation, id_step, "localhost_port", localhostPort ); rep.saveStepAttribute( id_transformation, id_step, "update_condition", updateCondition ); for ( int i = 0; i < localHosts.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, "local_host", localHosts[i] ); } for ( int i = 0; i < fieldTable.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, "stream_name", fieldTable[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "field_name", fieldStream[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "date_mask", dateMask[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "match_column", matchColumn[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "update_column", updateColumn[i] ); } // Also, save the step-database relationship! if ( databaseMeta != null ) { rep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() ); } } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.UnableToSaveStepInfoToRepository" ) + id_step, e ); } } public void getFields( RowMetaInterface rowMeta, String origin, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException { // Default: nothing changes to rowMeta } public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore ) { CheckResult cr; String error_message = ""; if ( databaseMeta != null ) { Database db = new Database( loggingObject, databaseMeta ); db.shareVariablesWith( transMeta ); try { db.connect(); if ( !Utils.isEmpty( tableName ) ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.TableNameOK" ), stepMeta ); remarks.add( cr ); boolean first = true; boolean error_found = false; error_message = ""; // Check fields in table String schemaTable = databaseMeta.getQuotedSchemaTableCombination( transMeta.environmentSubstitute( schemaName ), transMeta .environmentSubstitute( tableName ) ); RowMetaInterface r = db.getTableFields( schemaTable ); if ( r != null ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.TableExists" ), stepMeta ); remarks.add( cr ); // How about the fields to insert/dateMask in the table? first = true; error_found = false; error_message = ""; for ( int i = 0; i < fieldTable.length; i++ ) { String field = fieldTable[i]; ValueMetaInterface v = r.searchValueMeta( field ); if ( v == null ) { if ( first ) { first = false; error_message += BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.MissingFieldsToLoadInTargetTable" ) + Const.CR; } error_found = true; error_message += "\t\t" + field + Const.CR; } } if ( error_found ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.AllFieldsFoundInTargetTable" ), stepMeta ); } remarks.add( cr ); } else { error_message = BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.CouldNotReadTableInfo" ); cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } } // Look up fields in the input stream <prev> if ( prev != null && prev.size() > 0 ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.StepReceivingDatas", prev.size() + "" ), stepMeta ); remarks.add( cr ); boolean first = true; error_message = ""; boolean error_found = false; for ( int i = 0; i < fieldStream.length; i++ ) { ValueMetaInterface v = prev.searchValueMeta( fieldStream[i] ); if ( v == null ) { if ( first ) { first = false; error_message += BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.MissingFieldsInInput" ) + Const.CR; } error_found = true; error_message += "\t\t" + fieldStream[i] + Const.CR; } } if ( error_found ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.AllFieldsFoundInInput" ), stepMeta ); } remarks.add( cr ); } else { error_message = BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.MissingFieldsInInput3" ) + Const.CR; cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } } catch ( KettleException e ) { error_message = BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.DatabaseErrorOccurred" ) + e.getMessage(); cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } finally { db.disconnect(); } } else { error_message = BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.InvalidConnection" ); cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } // See if we have input streams leading to this step! if ( input.length > 0 ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.StepReceivingInfoFromOtherSteps" ), stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG, "GPLoadMeta.CheckResult.NoInputError" ), stepMeta ); remarks.add( cr ); } } public SQLStatement getSQLStatements( TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, Repository repository, IMetaStore metaStore ) throws KettleStepException { SQLStatement retval = new SQLStatement( stepMeta.getName(), databaseMeta, null ); // default: nothing to do! if ( databaseMeta != null ) { if ( prev != null && prev.size() > 0 ) { // Copy the row RowMetaInterface tableFields = new RowMeta(); // Now change the field names for ( int i = 0; i < fieldTable.length; i++ ) { ValueMetaInterface v = prev.searchValueMeta( fieldStream[i] ); if ( v != null ) { ValueMetaInterface tableField = v.clone(); tableField.setName( fieldTable[i] ); tableFields.addValueMeta( tableField ); } else { throw new KettleStepException( "Unable to find field [" + fieldStream[i] + "] in the input rows" ); } } if ( !Utils.isEmpty( tableName ) ) { Database db = new Database( loggingObject, databaseMeta ); db.shareVariablesWith( transMeta ); try { db.connect(); String schemaTable = databaseMeta.getQuotedSchemaTableCombination( transMeta.environmentSubstitute( schemaName ), transMeta .environmentSubstitute( tableName ) ); String sql = db.getDDL( schemaTable, tableFields, null, false, null, true ); if ( sql.length() == 0 ) { retval.setSQL( null ); } else { retval.setSQL( sql ); } } catch ( KettleException e ) { retval.setError( BaseMessages.getString( PKG, "GPLoadMeta.GetSQL.ErrorOccurred" ) + e.getMessage() ); } } else { retval.setError( BaseMessages.getString( PKG, "GPLoadMeta.GetSQL.NoTableDefinedOnConnection" ) ); } } else { retval.setError( BaseMessages.getString( PKG, "GPLoadMeta.GetSQL.NotReceivingAnyFields" ) ); } } else { retval.setError( BaseMessages.getString( PKG, "GPLoadMeta.GetSQL.NoConnectionDefined" ) ); } return retval; } public void analyseImpact( List<DatabaseImpact> impact, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, Repository repository, IMetaStore metaStore ) throws KettleStepException { if ( prev != null ) { /* DEBUG CHECK THIS */ // Insert dateMask fields : read/write for ( int i = 0; i < fieldTable.length; i++ ) { ValueMetaInterface v = prev.searchValueMeta( fieldStream[i] ); DatabaseImpact ii = new DatabaseImpact( DatabaseImpact.TYPE_IMPACT_READ_WRITE, transMeta.getName(), stepMeta.getName(), databaseMeta.getDatabaseName(), transMeta.environmentSubstitute( tableName ), fieldTable[i], fieldStream[i], v != null ? v.getOrigin() : "?", "", "Type = " + v.toStringMeta() ); impact.add( ii ); } } } public StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans trans ) { return new GPLoad( stepMeta, stepDataInterface, cnr, transMeta, trans ); } public StepDataInterface getStepData() { return new GPLoadData(); } public DatabaseMeta[] getUsedDatabaseConnections() { if ( databaseMeta != null ) { return new DatabaseMeta[] { databaseMeta }; } else { return super.getUsedDatabaseConnections(); } } public RowMetaInterface getRequiredFields( VariableSpace space ) throws KettleException { String realTableName = space.environmentSubstitute( tableName ); String realSchemaName = space.environmentSubstitute( schemaName ); if ( databaseMeta != null ) { Database db = new Database( loggingObject, databaseMeta ); try { db.connect(); if ( !Utils.isEmpty( realTableName ) ) { String schemaTable = databaseMeta.getQuotedSchemaTableCombination( realSchemaName, realTableName ); // Check if this table exists... if ( db.checkTableExists( schemaTable ) ) { return db.getTableFields( schemaTable ); } else { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.TableNotFound" ) ); } } else { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.TableNotSpecified" ) ); } } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.ErrorGettingFields" ), e ); } finally { db.disconnect(); } } else { throw new KettleException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.ConnectionNotDefined" ) ); } } /** * @return the schemaName */ public String getSchemaName() { return schemaName; } /** * @param schemaName * the schemaName to set */ public void setSchemaName( String schemaName ) { this.schemaName = schemaName; } public String getControlFile() { return controlFile; } public void setControlFile( String controlFile ) { this.controlFile = controlFile; } public String getDataFile() { return dataFile; } public void setDataFile( String dataFile ) { this.dataFile = dataFile; } public String getLogFile() { return logFile; } public void setLogFile( String logFile ) { this.logFile = logFile; } public String getNullAs() { return nullAs; } public void setNullAs( String nullAs ) { this.nullAs = nullAs; } public void setLoadAction( String action ) { this.loadAction = action; } public String getLoadAction() { return this.loadAction; } public void setLoadMethod( String method ) { this.loadMethod = method; } public String getLoadMethod() { return this.loadMethod; } public String getEncoding() { return encoding; } public void setEncoding( String encoding ) { this.encoding = encoding; } public void setDelimiter( String delimiter ) { this.delimiter = delimiter; } public String getDelimiter() { return delimiter; } public String getEnclosure() { return ""; } public boolean isEraseFiles() { return eraseFiles; } public void setEraseFiles( boolean eraseFiles ) { this.eraseFiles = eraseFiles; } public String getMaxErrors() { return maxErrors; } public void setMaxErrors( String maxErrors ) { this.maxErrors = maxErrors; } public void setEncloseNumbers( boolean encloseNumbers ) { this.encloseNumbers = encloseNumbers; } public boolean getEncloseNumbers() { return this.encloseNumbers; } public void setLocalHosts( String[] localHosts ) { this.localHosts = localHosts; } public String[] getLocalHosts() { return localHosts; } public void setLocalhostPort( String localhostPort ) { this.localhostPort = localhostPort; } public String getLocalhostPort() { return localhostPort; } public void setMatchColumns( boolean[] matchColumn ) { this.matchColumn = matchColumn; } public boolean[] getMatchColumn() { return matchColumn; } public void setUpdateColumn( boolean[] updateColumn ) { this.updateColumn = updateColumn; } public boolean[] getUpdateColumn() { return updateColumn; } public boolean hasMatchColumn() { for ( boolean matchColumn : this.matchColumn ) { if ( matchColumn ) { return true; } } return false; } public boolean hasUpdateColumn() { for ( boolean updateColumn : this.updateColumn ) { if ( updateColumn ) { return true; } } return false; } public void setUpdateCondition( String updateCondition ) { this.updateCondition = updateCondition; } public String getUpdateCondition() { return updateCondition; } }