// // DTSPump.h // Header file for the OLEDB DTSDataPump Service Provider. // Copyright 1997 Microsoft Corporation // #ifndef DTSDataPump_H_ #pragma option push -b -a8 -pc -A- /*P_O_Push*/ #define DTSDataPump_H_ #ifndef DTSDataPumpVersion_Major #define DTSDataPumpVersion_Major 1 #define DTSDataPumpVersion_Minor 0 #endif // DTSDataPumpVersion_Major #ifndef DTSDataPump_VersionOnly // The default Blob size used in this version of the DataPump. // May be overridden on a per-Transform or per-column basis. #define DTS_DEFAULT_INMEMORY_BLOB_SIZE (1024 * 1024) // Default number of successful InsertRows which will be Committed if supported by provider. // Currently set to 0 which means not to do a commit until all rows have been transferred. #define DTS_DEFAULT_InsertCommitSize 0 /////////////////////////////////////////////////////////////////////////////////////// // CPP and OleAut Enumerations and constants. /////////////////////////////////////////////////////////////////////////////////////// #ifndef DTSDataPump_CONSTANTS_ #define DTSDataPump_CONSTANTS_ // To avoid the need to cast on bitwise operations (which defeats typesafety anyway), // define the datatype as DWORD for C/CPP. OleAut languages don't do typechecking // and organize by the enum name. #ifdef DTSDataPump_ODL_ #define DP_ENUM_BEGIN(tdef, hstring) [helpcontext(H_##tdef), helpstring(hstring)] enum tdef // item = value, ... #define DP_ENUM_END(tdef) tdef, *LP##tdef #else #define DP_ENUM_BEGIN(tdef, hstring) DWORD tdef, *LP##tdef; enum tag##tdef // item = value, ... #define DP_ENUM_END(tdef) #endif typedef DP_ENUM_BEGIN(DTSDataPumpError, "Error ranges for DTSDataPump execution") { DTSDataPump_E_NotImplemented = 0x2000, DTSDataPump_E_RowsetsAlreadySet = 0x2001, DTSDataPump_E_TransformsAlreadySet = 0x2002, DTSDataPump_E_DestRowsetNotSupplied = 0x2003, DTSDataPump_E_RowsetsNotSupplied = 0x2004, DTSDataPump_E_SourceColumnsRequired = 0x2005, DTSDataPump_E_ColCountButNoCols = 0x2006, DTSDataPump_E_MismatchColOrdAndName = 0x2007, DTSDataPump_E_ColumnNameNotFound = 0x2008, DTSDataPump_E_ColumnOutOfRange = 0x2009, DTSDataPump_E_DestColumnAlreadySpecified = 0x200a, DTSDataPump_E_IDataConvertRequired = 0x200b, DTSDataPump_E_NullVariantIUnknown = 0x200c, DTSDataPump_E_NotReentrant = 0x200d, DTSDataPump_E_RowsetChangeMustInsert = 0x200e, DTSDataPump_E_DataPumpNotReentrant = 0x200f, DTSDataPump_E_DestColumnReadOnly = 0x2010, DTSDataPump_E_MustSpecifyDestOrTransform = 0x2011, DTSDataPump_E_BadTransformFlag = 0x2012, DTSDataPump_E_BadTransformStatusReturned = 0x2013, DTSDataPump_E_TransformServerException = 0x2014, DTSDataPump_E_CannotRebindColumn = 0x2015, DTSDataPump_E_InvalidFetchBufferSize = 0x2016, DTSDataPump_E_InvalidDTSBindMode = 0x2017, DTSDataPump_E_SourceBlobBinding = 0x2018, DTSDataPump_E_NonBlobStorageBind = 0x2019, DTSDataPump_E_LookupDupName = 0x201a, DTSDataPump_E_DestinationBlobBinding = 0x2020, DTSDataPump_E_Copy_NeedSrcAndDestColumns = 0x2024, DTSDataPump_E_Copy_ValidateSchemaError = 0x2025, DTSDataPump_E_Convert_DestNotNull = 0x2026, DTSDataPump_E_Convert_BadBindInfo = 0x2027, DTSDataPump_E_Convert_DestOverflow = 0x2028, DTSDataPump_E_Convert_SourceInvalidVariant = 0x2029, DTSDataPump_E_Convert_SourceInvalidLength = 0x202a, DTSDataPump_E_Convert_ConversionInvalid = 0x202b, DTSDataPump_E_Convert_ConversionFailed = 0x202c, DTSDataPump_E_Convert_ProviderOwnedTypeMismatch = 0x202d, DTSDataPump_E_Convert_BlobStorageNoInterface = 0x202e, DTSDataPump_E_AxScript_RequiredParams = 0x2040, DTSDataPump_E_AxScript_ValidateSchemaError = 0x2041, DTSDataPump_E_AxScript_ParseError = 0x2042, DTSDataPump_E_AxScript_BadTransformFunction = 0x2043, DTSDataPump_E_AxScript_CantChangeSrcCols = 0x2044, DTSDataPump_E_AxScript_CantResetAfterInitialize = 0x2045, DTSDataPump_E_AxScript_CantInitializeEngine = 0x2046, DTSDataPump_E_AxScript_RunTimeError = 0x2047, DTSDataPump_E_AutoBufferInterfaceNotSupported = 0x2051, DTSDataPump_E_InvalidSpecifyBlobDefaults = 0x2051, DTSDataPump_E_LineageVariableNotFound = 0x2052, DTSDataPump_E_LastRowCantBeLessThanFirst = 0x2053, DTSDataPump_E_DDQ_NeedTransformStatus = 0x2060, DTSDataPump_E_DDQ_NeedInsertQuery = 0x2061, DTSDataPump_E_DDQ_NeedUpdateQuery = 0x2062, DTSDataPump_E_DDQ_NeedDeleteQuery = 0x2063, DTSDataPump_E_DDQ_NeedUserQuery = 0x2064, DTSDataPump_E_DDQ_InformationNotSet = 0x2065, DTSDataPump_E_DDQ_BadTransformStatusContext = 0x2065, DTSDataPump_E_DDQ_DestColumnNotTransformed = 0x2066, DTSDataPump_E_DDQ_DestColumnNeedsLength = 0x2067, DTSDataPump_E_DDQ_DestDoesNotSupportSQL = 0x2068, } DP_ENUM_END(DTSDataPumpError); // These allow definition of how the transform will proceed. typedef DP_ENUM_BEGIN(DTSTransformFlags, "Flags (int or long) controlling Transform") { // No flags are specified; essentially, the conversion must be between exact types. // Note that this allows string <--> nonstring conversions, because every nonstring datatype // has a meaningful string representation. This may be overridden by RequireExactType, // which is even stricter. DTSTransformFlag_Strict = 0x00000000, // This flag means that IDTSDataPumpTransform::ValidateSchema should allow the transfer to proceed // even if there are potential overflows, under the assumption that the consumer is aware of this but // knows the source values are all (or mostly) within the destination column’s range. Any overflows during // transformation will cause the row to be exceptioned. This flag is generally of interest only to // the IID_IDTSDataPumpTransformCopy implementation, as this is a direct copy, whereas other // implementations would probably convert the values or determine validity on a specific case-by-case basis. // This value is also used for date/time conversions which result in loss, such as DATE -> DBTIME, // where a subset of the source value is still meaningful. DTSTransformFlag_AllowDemotion = 0x00000001, // This flag means that IDTSDataPumpTransform::ValidateSchema should allow the transfer to proceed // when there is promotion in the data range when moving from the source to the destination types, // such as I2->I4 or I4->float/double. Note that in some cases, such as I4->R4, the data range // increases but at the loss of some digits of precision. // If AllowLossless is specified, this is allowed by the Transform. DTSTransformFlag_AllowPromotion = 0x00000002, // This flag allows column (w)char or byte data to be truncated silently, such as when moving data // from a char(60) to a char(40) column. AllowDemotion is implied but overflow will be // silently truncated instead of causing an error. DTSTransformFlag_AllowStringTruncation = 0x00000004, // This flag means that IDTSDataPumpTransform::ValidateSchema should allow the transfer to proceed // even in the event that the source is a floating-point or numeric/decimal type and the destination // is an integral type. This is a numeric flavour of AllowDemotion and will not cause an error // (integer overflow will still be an error; i.e. left-of-decimal digits are significant). DTSTransformFlag_AllowNumericTruncation = 0x00000008, // This flag means that IDTSDataPumpTransform::ValidateSchema should allow the transfer to proceed // even if the source column allows NULL values and the destination column does not. As with // AllowDemotion, errors may be encountered during a transform. // If AllowLossless is specified, this is allowed by the Transform if going from nonNULLable to NULLable. DTSTransformFlag_AllowNullChange = 0x00000010, // This flag means that IDTSDataPumpTransform::ValidateSchema should allow the transfer to proceed // even in the event that the source and destination have a signed vs. unsigned mismatch. As with // AllowDemotion, errors may be encountered during a transform. // If AllowLossless is specified, this is allowed by the Transform when going from unsigned to signed // with promotion (e.g. UI2 -> I4). DTSTransformFlag_AllowSignChange = 0x00000020, // Require that the destination column's datatype be exactly the same as the source column's // (including length or precision/scale, fixed vs. variable length, sign, and nullability). // This overrides any other flags specified for column conversion validation. // Cannot be specified with ForceConvert. DTSTransformFlag_RequireExactType = 0x00000040, // Allow the conversion to proceed at all times, even when the source and destination types are // fundamentally different. Currently this applies to: // <--> bytes: Does a bitwise copy; caveats apply for endian, machine representations. // int/real <--> date: DATE is a double so this just converts between int and double. // real <--> date: DATE is a double so this just copies. // Cannot be specified with RequireExactType. DTSTransformFlag_ForceConvert = 0x00000080, // Causes the TransformServer to not ClearBindingData() the destination-row storage // for the columns in this Transform during OnRowComplete(). This allows the // destination row's values to be reused by the next transform. DTSTransformFlag_PreserveDestRows = 0x00000100, // Causes the TransformServer to allow all conversions for which a lossless conversion is // possible - e.g. Promotion, nonNULLable -> NULLable, unsigned -> promoted signed. DTSTransformFlag_AllowLosslessConversion = 0x00000200, // No flags are specified; essentially, the conversion must be between exact types. // Note that this allows string <--> nonstring conversions, because every nonstring datatype // has a meaningful string representation. This may be overridden by RequireExactType. DTSTransformFlag_Default = (DTSTransformFlag_AllowDemotion | DTSTransformFlag_AllowPromotion | DTSTransformFlag_AllowStringTruncation | DTSTransformFlag_AllowNumericTruncation | DTSTransformFlag_AllowNullChange | DTSTransformFlag_AllowSignChange) } DP_ENUM_END(DTSTransformFlags); // Status returned from a Transform operation. // All "normal" errors from DTSDataPumpTransform::Execute should be returned as // one of these flags, with a SUCCEEDED HRESULT (possibly with the addition of // OLEDB Error Records via the IDTSErrorRecords interface passed to // IDTSDataPumpTransform::AddVariable). A FAILED HRESULT returned from // DTSDataPumpTransform::Execute indicates an unrecoverable error and aborts // the DataPump. typedef DP_ENUM_BEGIN(DTSTransformStatus, "Return value (int or long) from ActiveX Scripting Transform") { // Default; conversions (if any) succeeded; write the row to destination if // specified, without calling any error handlers. Default is to do Insert; // this may be overridden for data-driven queries by other flags to do Insert, // Update, Delete, or UserQuery for a user-defined ad-hoc query. DTSTransformStat_OK = 0x00000001, // Success with additional info, which the app may want to process further // by reading its pvTransformUserData (if it shares that knowledge with the // transform server) or thru OLEDB Error Records; therefore, the Pump will // call the ErrorSink if one was specified, but does not increment the error // row count. The DTSTransformStatus result of the operation is passed to // the ErrorSink, so the app can switch on this bit. DTSTransformStat_Info = 0x00001000, // Write row if destination specified; also call ErrorSink with Info. DTSTransformStat_OKInfo = 0x00001001, // Abort further processing of this row, for non-error reasons. DTSTransformStat_SkipRow = 0x00000002, // Abort further processing of this row, and calls ErrorSink with Info. DTSTransformStat_SkipRowInfo = 0x00001002, // Do not fetch the next row; re-execute all transforms against the current // source and destination rows. No initialization is done to the destination // row, so this could be used to generate multiple output rows from a single // input row. Subsequent transforms are still executed unless a SkipRow* flag // is also present. DTSTransformStat_SkipFetch = 0x00000004, // Do not write the current row to destination. Usually used to fetch the next // source row to generate a simple aggregate. Subsequent transforms are still // executed unless a SkipRow* flag is also present. DTSTransformStat_SkipInsert // forces DTSTransformFlag_PreserveDestRows behaviour for the row for which it // is specified. DTSTransformStat_SkipInsert = 0x00000008, // The following 4 flags are not compatible together. They execute the // similarly-named statement passed to SetRowsetAndQueries on the Destination, // with values from the currently transformed Destination Row. DTSTransformStat_InsertQuery = 0x00000010, DTSTransformStat_UpdateQuery = 0x00000020, DTSTransformStat_DeleteQuery = 0x00000040, DTSTransformStat_UserQuery = 0x00000080, // May be bit-OR'd into the following error returns. DTSTransformStat_Error = 0x00002000, // Abort further processing of this row due to error and call the error sink, // but do not write to exception file. Should be handled by the ErrorSink. DTSTransformStat_ErrorSkipRow = 0x00002002, // Abort further processing of this row as an exception and call the error sink, // and write this row to exception file. Should be handled by the ErrorSink. // Note this bit does not map to any non-error bits. DTSTransformStat_ExceptionRow = 0x00002100, // Or’d with prior bits to abort processing any further rows and return // DTSTransformExec_AbortPump from IDTSDataPump::Execute(). // This does not include the Error bit so &'ing with it will only return // TRUE for this bit. DTSTransformStat_AbortPump = 0x00004000, // Transform determined that this row is the last one to be operated on, // so allows the pump to be aborted "normally" (without signifying an error). // May be or'd with other bits to skip the current row; otherwise it will go // to the next transforms and then write it to destination (in accordance with // how the following transforms specify). DTSTransformStat_NoMoreRows = 0x00008000, } DP_ENUM_END(DTSTransformStatus); // Status returned from an IDataPump::Execute operation. typedef DP_ENUM_BEGIN(DTSExecuteStatus, "Return value (int or long) from DataPump Execution") { // All rows copied (or skipped) without error. DTSTransformExec_OK = 0x00000000, // Bit-OR’d into the following error returns. DTSTransformExec_Error = 0x00001000, // Bit-or’d into following // Pump continued to completion but errors were encountered DTSTransformExec_OKErrors = 0x00001001, // Pump aborted because too many rows had errors. DTSTransformExec_ErrorCountExceeded = 0x00001002, // Pump aborted due to Transform request or ErrorSink return. DTSTransformExec_AbortPump = 0x00001004, } DP_ENUM_END(DTSExecuteStatus); #endif // DTSDataPump_CONSTANTS_ //////////////////////////////////////////// // CPP-only definitions //////////////////////////////////////////// #ifndef DTSDataPump_ODL_ // Define parameter usage. #define DP_IN #define DP_OUT #define DP_INOUT #ifdef NONAMELESSUNION #define DP_UNION_NAME(u) u #else #define DP_UNION_NAME(u) #endif // For safety, struct initialization values are set in ctors for C++ clients. #if !defined(__cplusplus) && !defined(DP_NO_AUTOCTOR) #define DP_NO_AUTOCTOR #endif // These are the conversion flags indicating what may happen during an individual column // Convert() call, and accounts for the column lengths, nullability, sign, etc. // See DTSTransformFlags for a more detailed discussion of the similarly-named TransformFlag // which will allow conversion to proceed when these conditions are present. // Keys: // - TransformFlag is available to explicitly allow this. // - Error may be encountered during Convert() // - Fatal; Convert() will error as unsupported or with overflow. // typedef DP_ENUM_BEGIN(DTSConvertFlags, "DTSConvertFlags") { // The conversion is between columns of identical type, length or precision/scale, // and nullability, or is between text and another type, with the text being of // sufficient length for a representation of that datatype. Errors should not be // encountered during Convert() unless a text conversion contains invalid data. DTSConvertFlag_ExactType = 0x00000000, // The conversion will promote the range of data from source to destination // (e.g. I4 -> I2, [var]char -> longer [var]char, numeric(x, y) -> numeric(x+1, y+1)). // DTSConvertFlag_Promotion = 0x00000001, // Conversion will demote (e.g. I4 -> I2); overflow error possible. // DTSConvertFlag_Demotion = 0x00000002, // Conversion may do string or byte truncation; truncation error possible if // this flag is not specified on Convert(). // DTSConvertFlag_StringTruncation = 0x00000004, // Conversion may do integral rounding from float or numeric, or move a larger // scale into a smaller scale (both cases resulting in truncation of digits to // the right of the decimal point). This is also flagged when moving from integral // or numeric to float/double when source precision is greater than FLT/DBL_DIG. // DTSConvertFlag_NumericTruncation = 0x00000008, // Conversion may try to put NULL source data into a NonNULL destination column, // which will error, or vice-versa, which will be safe. // DTSConvertFlag_NullChange = 0x00000010, // Conversion may try to put a signed value int/float into an unsigned destination, // or vice-versa. This may error if the source value is negative and destination // is unsigned, or if the source is unsigned and its value is larger than the // signed destination's maximum signed value (overflow). // DTSConvertFlag_SignChange = 0x00000020, // Destination column size is too short for a meaningful conversion from source // column type. // DTSConvertFlag_DestTooShort = 0x00000040, // Source column size is too short for a meaningful conversion to destination // column type. // DTSConvertFlag_SourceTooShort = 0x00000080, // Source and destination datatypes are not really compatible, but conversion can be forced. // DTSConvertFlag_ForceConvert = 0x00000100, // Conversion fails because of bad or incompatible column types. // DTSConvertFlag_Unsupported = 0x00001000, } DP_ENUM_END(DTSConvertFlags); // Binding modes for column data; returned from IDTSDataPumpTransform::ValidateSchema // via DTSTransformColumnInfo. Normally the DataPump default handling does not need to // be changed, but for Blob ((DBCOLUMNFLAGS_ISLONG) columns, custom Transforms are able // to adjust bindings to maximize performance. // typedef DP_ENUM_BEGIN(DTSBindMode, "DTSBindMode") { // Indicates data should be bound "in-memory, out of line". Currently this is only supported // by the OLEDB specification for variable-length types: DBTYPE_((W)STR|BYTES); therefore, // the DataPump will error if it is specified for other types. DTSBindMode_(Client|Provider)Owned // must be specified with DTSBindMode_Byref. // // For source, the returned data will be a direct pointer to the provider's data if // DTSBindMode_ProviderOwned is specified (in which case it must not be free'd or written to), // or a CoTaskMemAlloc()'d pointer if DTSBindMode_ClientOwned is specified (in which case it // is the client's property and must be freed). // // For destination, the transformation server must place the data pointer in // pDestColumnInfo->pvRowData. If DTSBindMode_ClientOwned is specified, then the data // is assumed to require freeing after the InsertRow operation completes. The DataPump // will never perform a non-Byref, in-memory destination binding for a Blob, so this flag // must be specified unless a Storage Object is used. // DTSBindMode_Byref = 0x00000001, // Default "in-memory, inline" binding mode; space for the source and destination data, including // the full length of a DBTYPE_((W)STR|BYTES) column, is allocated in rgColumnData[ii].pvData and // passed to IDTSDataPumpTransform::Execute. // // For a BLOB (DBCOLUMNFLAGS_ISLONG) column, IDTSDataPumpTransform::ValidateSchema returns // the length to use for this binding in ppDTSColBinding[ii].cbInMemoryBlobSize. This will // result in a separate allocation for that Blob column (i.e. multiple Blobs are not // allocated within a single contiguous row). // // On fetch from Source, the DBSTATUS in the binding will indicate whether the data was // truncated; it is up to the Transform server how (or if) this is handled. // // For performance reasons, this flag should not be specified for non-Blob (W)STR|BYTES // source columns; DTSBindMode_Byref_ProviderOwned is the default, to use a pointer to the // provider's data cache and avoid an unnecessary copy. // // For DBTYPE_BSTR and DBTYPE_VARIANT, this specifies that the binding is DBMEMOWNER_CLIENTOWNED // (without BYREF), and the client is responsible for freeing it (e.g. IDTSDataConvert::ClearBindingData). // DTSBindMode_ClientOwned = 0x00000002, // For Source DBTYPE_((W)STR|BYTES), this flag causes the OLEDB binding to be done as DBTYPE_BYREF // with DBMEMOWNER_CLIENTOWNED, resulting in a CoTaskMemAlloc which the client is // responsible for freeing (e.g. via IDTSDataConvert::ClearBindingData). For a BLOB // column, the length to use for this binding is returned from ValidateSchema() in // ppDTSColBinding[ii].cbInMemoryBlobSize. On fetch from Source, the DBSTATUS in the binding // will indicate whether the data was truncated; it is up to the Transform server how (or if) // this is handled. // // This flag causes each row to have a separate CoTaskMemAlloc for the source column. This is // somewhat less efficient than the other in-memory options, and thus should only be used by // a Transform which wants to assume ownership of that allocation. The Transform is responsible // for tracking and freeing the allocation (and for ensuring that OnRowComplete does not free // it if it is to be used in subsequent Transforms). // // For destination columns, this is the "safest" way to pass an in-memory pointer, as some providers // may not allow ProviderOwned on a destination (such as with Blob columns). The Transform must // ensure that it does not double-free a pointer. // DTSBindMode_Byref_ClientOwned = 0x00000003, // By itself, ProviderOwned is seldom used by itself except for BSTR, which does not always // support Byref. It is primarily for DBTYPE_((W)STR|BYTES) with Byref, to reduce allocations // and/or copies, as described below. It may not be supported by providers for other datatypes. // DTSBindMode_ProviderOwned = 0x00000004, // This flag causes source columns to be bound to return a pointer into the provider's memory // space for DBTYPE_((W)STR|BYTES). This pointer is read-only and must not be freed. // // For Blob columns, the Source Provider may not support (Byref_)ProviderOwned Blobs; this // would require that the entire Blob be buffered contiguously. Therefore, unless you have // specific knowledge of the provider, this flag is discouraged. // // For DBTYPE_BSTR, the BYREF specification may not be supported, and may require DBMEMOWNER_PROVIDEROWNED // (without BYREF). The client must not free the data. // // For other types, including DBTYPE_VARIANT, OLEDB raises an error for this specification // when creating an accessor. // // For the destination, specifying ProviderOwned requires that the data be shallow-copied into // the destination binding to avoid memory leaks (this is automatically done by IDTSDataConvert:: // ConvertToBinding). // DTSBindMode_Byref_ProviderOwned = 0x00000005, // This indicates whether the Pump should buffer Source Blob Storage Objects. For most cases, // this should be left _BufferDefault; for performance reasons, the DataPump will only buffer // where it is necessary to avoid data loss. This is in the following cases: // DTSBindMode_Blob_BufferAlways // DTSBindMode_Blob_BufferDefault, provider doesn't allow multiple SO's, and any of following: // The column is referenced in a subsequent transform. // The column is not the rightmost column of all transforms up to and including it. // // The DataPump can buffer from a source provider's ISequentialStream or ILockBytes, and // exposes both these interfaces on its own object. Because it is a buffer, the object's data // can be edited via Write(At) to reduce memory requirements in the TransformServer (allowing the // source object to be placed in the destination row, if the destination supports Storage Objects). // // DTSBindMode_Blob_* is ignored for in-memory binding, which is an implicit buffering. DTSBindMode_Blob_BufferDefault = 0x00000010, DTSBindMode_Blob_BufferAlways = 0x00000020, DTSBindMode_Blob_BufferNever = 0x00000040, // This indicates whether to use a Structured Storage object for binding a BLOB column. The Transform // Server should indicate which interface it wants in DTSBindInfo::fStorageObject, on return from // ValidateSchema(). The DataPump supports the following behaviour: // Custom Transformations: // For Source, if the DataPump does not buffer, only the provider-supported Storage Object interfaces // are available. Generally this will always include ISequentialStream. See comments regarding // DTSBindMode_Blob_Buffer*; if the DataPump buffers the Blob data, it supports only ISequentialStream // and ILockBytes. // If the source does not support storage objects, then the Transform Server must not request a // Storage Object, and must bind the source data as in-memory, specifying DTSBindInfo::cbInMemoryBlobSize. // For Destination, the Transform Server supplies the Storage object placed into the row, and must // specify one interface from fProviderStorageObjects for the DataPump to bind the destination. // If the destination does not support storage objects, then the TransformServer must not request // a Storage Object, and must bind the destination data as in-memory, ClientOwned or ProviderOwned, // specifying DTSBindInfo::cbInMemoryBlobSize. // Default (DataPump-supplied) TransformCopy: // If either Source or Destination do not support ISequentialStream, then the DataPump will bind both // as ClientOwned in-memory, using the source column's DTSBindInfo::cbInMemoryBlobSize. // Otherwise, the DataPump will bind to the providers as ISequentialStream, with default buffering. // See also comments regarding DTSBindMode_Blob_Buffer*; this can be specified to override the // Pump's default handling even in the TransformCopy case. // // DTSBindMode_Blob_StorageObject cannot be specified with non-DTSBindMode_Blob_* flags. DTSBindMode_Blob_StorageObject = 0x00000100, } DP_ENUM_END(DTSBindMode); // Indicates which of the DataPump defaults are to be overridden on a single AddTransform(). typedef DP_ENUM_BEGIN(DTSSpecifyBlobDefaults, "Specify overrides of DataPump Blob-handling defaults") { DTSBlobDefault_DataPumpDefaults = 0x0000, // None (initialization) DTSBlobDefault_BufferSource = 0x0001, // Override DTSBindMode_Blob_BufferDefault for source Blob Storage Objects DTSBlobDefault_InMemorySize = 0x0002, // Override DTS_DEFAULT_INMEMORY_BLOB_SIZE. DTSBlobDefault_ForceInMemory = 0x0004, // Force Blobs to be InMemory (no Storage Objects) for this Transform. // Forces DTSTransformColumnInfo.fProviderStorageObjects // sent to the Transformer to be 0. DTSBlobDefault_ForceMultipleStorageObjects = 0x0008, // Forces DTSTransformColumnInfo.dtsProviderFlags sent to the // Transformer to include DTSProviderFlag_Blob_MultipleStorageObjects. // This could be an optimization if the Source provider supports multiple // storage objects and the destination is known to support them only // multiple blobs for insert, since the OLEDB spec does not distinguish // between multiple-StorageObject support for GetData vs. SetData/Insert. } DP_ENUM_END(DTSSpecifyBlobDefaults); // Flags indicating known Provider Blob capabilities; their absence indicates // corresponding Provider restrictions or requirements. typedef DP_ENUM_BEGIN(DTSProviderFlags, "Provider behaviour characteristics") { DTSProviderFlag_None = 0x00000000, // None DTSProviderFlag_ProviderOwned = 0x00000001, // Provider supports Byref binding (some may not). DTSProviderFlag_Blob_InsertNoLength = 0x00000100, // Blob Inserts do not require length to be prespecified DTSProviderFlag_Blob_Revisitable = 0x00000200, // Provider guarantees that Blob data is not skipped when succeeding columns fetched DTSProviderFlag_Blob_Rewindable = 0x00000400, // Provider guarantees Blob data supports random access DTSProviderFlag_Blob_ProviderOwned = 0x00000800, // Provider allows the PROVIDEROWNED flag for use with Blobs DTSProviderFlag_Blob_MultipleStorageObjects = 0x00001000, // Provider supports multiple storage objects per row. DTSProviderFlag_Blob_NonBlockingStorageObjects = 0x00002000, // Provider supports multiple nonblocking storage objects per row. } DP_ENUM_END(DTSProviderFlags); // The actual structure passed to AddTransform to specify overriding Blob defaults. // This is most useful for the default TransformCopy case, but can also be used by // a client who predetermines (e.g. via a query) the maximum Blob size in the coming // result set, for the most efficient memory allocations. #ifndef DP_NO_AUTOCTOR struct DTSTransformBlobDefaults { #else // DP_NO_AUTOCTOR typedef struct { #endif // DP_NO_AUTOCTOR DTSSpecifyBlobDefaults dtsSpecifyMask; // Which of the following items to override. BOOL bBufferSource; // If dtsSpecifyMask & DTSBlobDefault_BufferSource; // TRUE or FALSE forces Pump to buffer source Blobs or not. ULONG cbInMemorySize; // If dtsSpecifyMask & DTSBlobDefault_InMemorySize; // overrides DTS_DEFAULT_INMEMORY_BLOB_SIZE. Size in bytes. #ifndef DP_NO_AUTOCTOR DTSTransformBlobDefaults() : dtsSpecifyMask(DTSBlobDefault_DataPumpDefaults) { } }; #else // DP_NO_AUTOCTOR } DTSTransformBlobDefaults; #endif // DP_NO_AUTOCTOR typedef DTSTransformBlobDefaults *LPDTSTransformBlobDefaults; typedef const DTSTransformBlobDefaults *LPCDTSTransformBlobDefaults; // Specifies an individual column passed to AddTransform. The column may be specified by // name, or if the name is NULL, by an ordinal (this makes unnamed columns easier for the // consumer to specify). typedef struct { LPOLESTR pwzColumnName; // Name of column ULONG ulColumnOrdinal; // Ordinal of column if name is NULL; 1-based for OLEDB consistency. } DTSTransformColumnSpecification, *LPDTSTransformColumnSpecification; typedef const DTSTransformColumnSpecification *LPCDTSTransformColumnSpecification; // Specifies a list of columns passed to AddTransform. #ifndef DP_NO_AUTOCTOR struct DTSTransformColumnsSpecification { #else // DP_NO_AUTOCTOR typedef struct { #endif // DP_NO_AUTOCTOR ULONG cSourceColumns; // Specify source columns LPCDTSTransformColumnSpecification pSourceColumns; ULONG cDestinationColumns; // Specify destination columns LPCDTSTransformColumnSpecification pDestinationColumns; DTSTransformBlobDefaults BlobDefaults; // Blob default overrides if specified #ifndef DP_NO_AUTOCTOR DTSTransformColumnsSpecification() : cSourceColumns(0) , pSourceColumns(NULL) , cDestinationColumns(0) , pDestinationColumns(NULL) { } }; #else // DP_NO_AUTOCTOR } DTSTransformColumnsSpecification; #endif // DP_NO_AUTOCTOR typedef DTSTransformColumnsSpecification *LPDTSTransformColumnsSpecification; typedef const DTSTransformColumnsSpecification *LPCDTSTransformColumnsSpecification; // Specifies a query and list of columns for IDTSDataDrivenQuery. #ifndef DP_NO_AUTOCTOR struct DTSTransformQuerySpecification { #else // DP_NO_AUTOCTOR typedef struct { #endif // DP_NO_AUTOCTOR LPCOLESTR wzQuery; // The Parameterized Query ULONG cColumns; // Specify count of columns LPCDTSTransformColumnSpecification pColumns; // Specify column mapping to parameters, in order found in query. #ifndef DP_NO_AUTOCTOR DTSTransformQuerySpecification() : wzQuery(NULL) , cColumns(0) , pColumns(NULL) { } }; #else // DP_NO_AUTOCTOR } DTSTransformQuerySpecification; #endif // DP_NO_AUTOCTOR typedef DTSTransformQuerySpecification *LPDTSTransformQuerySpecification; typedef const DTSTransformQuerySpecification *LPCDTSTransformQuerySpecification; // Transform-server specifiable binding information. An array of these structures is passed to // ValidateSchema() with default values (possibly derived from DTSTransformBlobDefaults overrides), // and the Transform Server can set the values. Because source columns can appear multiple times // in the same or different transactions, the last specification wins; therefore, a TransformServer's // Execute() method should gracefully handle a source binding different from what it specified in // ValidateSchema(). typedef struct { DTSBindMode eBindMode; // Per above. For Blobs, specifying a Buffering mode overrides // the DataPump and any DTSTransformBlobDefaults default. DWORD fStorageObject; // For DTSBindMode_Blob_StorageObject; one of DBPROPVAL_SS_*. If // specified, eBindMode must be DTSBindMode_Blob_StorageObject. ULONG cbInMemoryBlobSize; // For DTSBindMode of inmemory Blobs. Setting this value overrides // the DataPump and any DTSTransformBlobDefaults default. Size in bytes. } DTSBindInfo; // This is a single column definition, binding, and data item for DTSTransformColumnInfo. typedef struct { const DBCOLUMNINFO *pDBColumnInfo; // Pointer to source or destination DBCOLUMNINFO for this column. const DBBINDING *pDBBinding; // Pointer to source or destination DBBINDING for this column. // wType == DBTYPE_EMPTY if this column is not referenced in any transform. DTSBindInfo *pDTSBindInfo; // Pointer to source or destination DTSBindInfo for this column. LPBYTE pvData; // Data space for this column, indexed by pDBBinding offsets. // NULL if this column was not referenced in any Transform. } DTSColumnData; // The DBCOLUMNFLAGS and pwszName are in DBCOLUMNINFO and not DBBINDING; // therefore pass both structures to transform code. The COM Transform server uses the // binding info to access the pvRowData. This structure is passed to ITransformExecute:: // Execute to expose the source and destination columns specified by the Transform. typedef struct { DWORD fProviderStorageObjects; // DBPROPVAL_SS_*; Blob Storage Object interfaces supported // by source or destination provider. Will be 0 if none supported, // or if DTSTransformBlobDefaults::bForceBlobsInMemory is specified. DTSProviderFlags dtsProviderFlags; // Provider characterstics, e.g Blob Flags. ULONG cColumns; // Count of columns in rgColumns DTSColumnData *rgColumnData; // Column schema and binding information ULONG cPriorBlobStorageObjects; // Number of Blobs bound as Storage Objects in prior transforms. // Can be used with DTSProviderFlag_Blob_MultipleStorageObjects // to determine if the current Transform can use a storage object. } DTSTransformColumnInfo, *LPDTSTransformColumnInfo; typedef const DTSTransformColumnInfo *LPCDTSTransformColumnInfo; typedef enum { DTSGuid_Variant, DTSGuid_Guid, DTSGuid_OleStr } DTSGuidType; typedef struct { DTSGuidType eType; // Indexes union. union { GUID Guid; // GUID form VARIANT Variant; // BSTR == progid or clsid (differentiated by looking for ‘.’ in name) // BYTE/LONG == guid encoding (e.g. Repository)) // UNKNOWN == pointer to IID_IDTSDataPumpTransform LPOLESTR OleStr; // Progid or clsid (differentiated by looking for ‘.’ in name) } DP_UNION_NAME(u); } DTSGuid; #define DTS_DEFAULT_LookupCacheSize 100 // Specifies a query and list of columns for IDTSDataDrivenQuery. #ifndef DP_NO_AUTOCTOR struct DTSTransformLookupSpecification { #else // DP_NO_AUTOCTOR typedef struct { #endif // DP_NO_AUTOCTOR LPCOLESTR wzName; // Name of the Lookup (for disambiguation) LPCOLESTR wzQuery; // The Parameterized Query IUnknown *pIUnkSession; // Session to use for the Lookup ULONG cMaxCacheRows; // Number of rows to cache #ifndef DP_NO_AUTOCTOR DTSTransformLookupSpecification() : wzName(NULL) , wzQuery(NULL) , pIUnkSession(NULL) , cMaxCacheRows(DTS_DEFAULT_LookupCacheSize) { } }; #else // DP_NO_AUTOCTOR } DTSTransformLookupSpecification; #endif // DP_NO_AUTOCTOR typedef DTSTransformLookupSpecification *LPDTSTransformLookupSpecification; typedef const DTSTransformLookupSpecification *LPCDTSTransformLookupSpecification; /////////////////////////////////////////////////////////////////////////////////////// // Class and IID definitions /////////////////////////////////////////////////////////////////////////////////////// // Forward-define all interfaces. #define DP_FWD_DEFINE_INTERFACE(itf) \ interface itf; \ typedef interface itf * LP##itf; // Repeat the IUnknown and IDispatch members because C doesn't provide inheritance. #ifndef DTSDataPump_Unknown_Base #define DTSDataPump_Unknown_Base() \ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; \ STDMETHOD_(ULONG,AddRef) (THIS) PURE; \ STDMETHOD_(ULONG,Release) (THIS) PURE; #endif #ifndef DTSDataPump_Dispatch_Base #define DTSDataPump_Dispatch_Base(itf) \ DTSDataPump_Unknown_Base() \ STDMETHOD(GetTypeInfoCount)(UINT FAR* pcTypeInfo) PURE; \ STDMETHOD(GetTypeInfo)(UINT iTypeInfo, LCID lcid, ITypeInfo FAR* FAR* ppTI) PURE; \ STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR FAR* rgszNames, UINT cNames, \ LCID lcid, DISPID FAR* rgdispid) PURE; \ STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, \ DISPPARAMS FAR* pdispparams, LPVARIANT pvarResult, \ LPEXCEPINFO pexcepinfo, UINT FAR* puArgErr) PURE; #endif #ifndef DTSDataPump_IDispatch #define DTSDataPump_IDispatch IDispatch #endif // Include to define ownership of these GUIDs. // {xxxxxxxx-740b-11d0-ae7b-00aa004a34d5} #define DEFINE_DTSDataPumpGUID(name, lval) \ DEFINE_GUID(name, 0x##lval, 0x740b, 0x11d0, 0xae, 0x7b, 0x0, 0xaa, 0x0, 0x4a, 0x34, 0xd5); // DTSPump-supplied classes and interfaces. DP_FWD_DEFINE_INTERFACE(IDTSDataPump) #define Progid_DTSDataPump OLESTR("DTS.DataPump") DEFINE_DTSDataPumpGUID(CLSID_DTSDataPump, 10010100) DEFINE_DTSDataPumpGUID(IID_IDTSDataPump, 10010101) #define Progid_DTSErrorLookup OLESTR("DTS.ErrorLookup") DEFINE_DTSDataPumpGUID(CLSID_DTSErrorLookup, 10010102) DP_FWD_DEFINE_INTERFACE(IDTSDataConvert) #define Progid_DTSDataConvert OLESTR("DTS.DataConvert") DEFINE_DTSDataPumpGUID(CLSID_DTSDataConvert, 10010103) DEFINE_DTSDataPumpGUID(IID_IDTSDataConvert, 10010104) DEFINE_DTSDataPumpGUID(IID_IDTSDataDrivenQuery, 10010105) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpSpecifyLookups, 10010106) // DTS Typelib IID's. DEFINE_DTSDataPumpGUID(LIBID_DataPump, 10010200) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpColumns) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpColumns, 10010201) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpColumn) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpColumn, 10010202) DEFINE_DTSDataPumpGUID(IID_IDTSErrorRecords, 10010203) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpLookups) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpLookups, 10010204) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpLookup) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpLookup, 10010205) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpLookupVariant) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpLookupVariant, 10010206) // Repository Storage IIDs. DEFINE_DTSDataPumpGUID(IID_IDTSRepositoryProvider, 100202F1) DEFINE_DTSDataPumpGUID(IID_IDTSRepositoryStorage, 100202F2) ///////////////////////////////////////////////////////////////////////////////// // Category id of DTS custom transforms. ///////////////////////////////////////////////////////////////////////////////// DEFINE_DTSDataPumpGUID(CATID_DTSCustomXform, 10010100) //we will use the same id as the pump clsid. // Consumer-supplied classes and interfaces. DP_FWD_DEFINE_INTERFACE(IDTSDataPumpTransform) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpTransform, 10010300) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpErrorSink) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpErrorSink, 10010301) DP_FWD_DEFINE_INTERFACE(IDTSDataPumpProgressSink) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpProgressSink, 10010302) DP_FWD_DEFINE_INTERFACE(IDTSDataDrivenQuerySink) DEFINE_DTSDataPumpGUID(IID_IDTSDataDrivenQuerySink, 10010303) // DTSDataPump-supplied COM Transform Servers // A "Transformation Server" coclass consists of: // coclass TTransformServer { // required IDTSDataPumpTransform; // // // The following are optional if the TransformServer has no custom // // properties requiring editing. If it has, these are required. // optional ; // optional ISpecifyPropertyPages; // optional IPropertyPage; // optional IPersistPropertyBag; // } #define Progid_DTSDataPumpTransformCopy OLESTR("DTS.DataPumpTransformCopy") DEFINE_DTSDataPumpGUID(CLSID_DTSDataPumpTransformCopy, 10010400) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpTransformCopy, 10010401) // No custom properties, therefore no custom interface or IID. #define Progid_DTSDataPumpTransformScript OLESTR("DTS.DataPumpTransformScript") DEFINE_DTSDataPumpGUID(CLSID_DTSDataPumpTransformScript, 10010501); DP_FWD_DEFINE_INTERFACE(IDTSDataPumpTransformScriptProperties) DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpTransformScriptProperties, 10010502); DEFINE_DTSDataPumpGUID(IID_IDTSDataPumpTransformScript, 10010503); //optional interface to be implemented by custom transform providers - used by DTS UI to configure the transforms DEFINE_DTSDataPumpGUID(IID_IDTSCustomTransformUI, 10010601); //////////////////////////////////////////////////////////////////////////////////////// // // DataPump-supplied Transform variables. // // These are passed to IDTSDataPumpTransform::AddVariable. They are all of type // VT_VARIANT. IDTSErrorRecords (interface defined below) allows any transform // to append OLEDB Error Records to IErrorInfo for the current thread. The name // "DTSErrorRecords" is what is passed to IDTSDataPumpTransform::AddVariable; the // VT_DISPATCH ma be QI'd (or cast) to IDTSErrorRecords. This object is also // inserted into ActiveX Scripting namespaces invoked by the Pump. All DTS-generated // variables are inserted into ActiveX scripting namespaces as non-global variables // (i.e. their methods must be qualified with the object name). // // Name Type // ---- ---- // DTSError DTS.Error #define wzDTSErrorRecords OLESTR("DTSErrorRecords") // // These are inserted by name into the global namespace of an ActiveX scripting transform. // View the type library to see the type definitions. Note that the return value from the // method (FunctionEntry) must be an integral type. // // Name Type // ---- ---- // DTSSource DTS.Columns // DTSDestination DTS.Columns // (return value) adInt or adSmallInt (DTSTransformStatus) // // // These are inserted by name into the global namespace of an ActiveX scripting transform, // as well as being passed to IDTSDataPumpTransform::AddVariable. // // Name Type // ---- ---- // DTSLookups DTS.Lookups #define wzDTSLookups OLESTR("DTSLookups") // These are the DTS-Package-supplied global variables, if the Pump is being run from // the Package. #define wzDTSGlobalVariables OLESTR("DTSGlobalVariables") // These are special pseudo-columnnames corresponding to Lineage. They are also // the names of the corresponding GlobalVariables; TransformCopy will automatically // map them over to the specified destination column. These names must not be used // by source column names. #define wzDTSLineage_FullString OLESTR("DTSLineage_Full") #define wzDTSLineage_IntegerCRC OLESTR("DTSLineage_Short") //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// // // DataPump-supplied interface definitions. // //////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////// // IDTSDataPump - Primary interface to specify source and destination rowsets, // add Transforms, and Execute() the transfer. AddTransform will error if // SetRowsets has not been called, and SetRowsets will error if any transforms // have been added (because ValidateSchema has been done on them already). // InitNew() reinitializes the IDTSDataPump object. Execute returns E_FAIL if aborted, // DB_E_ERRORSOCCURRED if max error count exceeded; DB_S_ERRORSOCCURRED if errors // less than the max allowed occurred, possible provider-specific errors, or NOERROR // if completed with no errors. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPump DECLARE_INTERFACE_(IDTSDataPump, IUnknown) { DTSDataPump_Unknown_Base() STDMETHOD(InitNew)(THIS) PURE; STDMETHOD(GetRowsets)(THIS_ DP_OUT IRowset **ppSrcRowset, DP_OUT IRowsetChange **ppDestRowsetChange ) PURE; STDMETHOD(SetRowsets)(THIS_ DP_IN IRowset *pSrcRowset, // Must be able to retrieve these rows DP_IN IRowsetChange *pDestRowsetChange // Must have DBPROP_UPDATABILITY: DPBROP_UP_INSERT ) PURE; STDMETHOD(SetProgressRowCount)(THIS_ DP_IN ULONG cIn // Interval for IDTSDataPumpProgressSink::OnIntervalComplete; default == 1000 ) PURE; STDMETHOD(SetMaximumErrorRowCount)(THIS_ DP_IN ULONG cIn // Maximum allowable error rows; default = 0 (abort on first error row). ) PURE; STDMETHOD(SetFetchBufferSize)(THIS_ DP_IN ULONG cIn // Size of the GetNextRows HROW buffer (default = 1) ) PURE; STDMETHOD(SetInsertCommitSize)(THIS_ DP_IN ULONG cIn // Number of successful InsertRows between "Commits", if supported by provider (default == 0; all rows in one batch). ) PURE; STDMETHOD(AddTransform)(THIS_ DP_IN LPCOLESTR pwzName, // Transform name DP_IN LPBYTE pvUserData, // Will be passed to Sink if event occurs on Transform. DP_IN LPCDTSTransformColumnsSpecification pColumns, // Source and destination columns DP_IN DTSGuid ServerClsid, // COM server ProgID or CLSID or IUnknown DP_IN VARIANT ServerParameters, // Parameters to server for this transform DP_IN DTSTransformFlags dwFlags, // Transformation column-validation flags DP_IN IStorage *pIStorage // Pointer to persistent storage of Transform properties ) PURE; STDMETHOD(AddTransformVariable)(THIS_ DP_IN LPCOLESTR pwzName, // Variable name DP_IN BOOL bGlobal, // For ActiveX scripts, indicates whether this variable's // methods must be qualified by the object name. DP_IN VARIANT Variable // Variable value; passed to and updatable by Transform ) PURE; STDMETHOD(Execute)(THIS_ DP_IN LPBYTE pvUserData, // User data passed back to Sinks. DP_OUT ULARGE_INTEGER *puliRowsComplete, // Total number of source rows processed (including those skipped). DP_OUT ULONG *pulErrorRows, // Total number of error rows encountered. DP_OUT LPDTSExecuteStatus pExecStatus // Pump return status. ) PURE; STDMETHOD(SetFirstRow)(THIS_ DP_IN ULARGE_INTEGER cIn // First source row to copy. Default is 1 (first row). ) PURE; STDMETHOD(SetLastRow)(THIS_ DP_IN ULARGE_INTEGER cIn // Last source row to copy. Default is 0 (copy all rows). ) PURE; }; /////////////////////////////////////// // IDTSDataDrivenQuery - Allows specification of individual queries instead // of simple Insert at the Destination. QI'd from IDTSDataPump. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataDrivenQuery DECLARE_INTERFACE_(IDTSDataDrivenQuery, IUnknown) { DTSDataPump_Unknown_Base() // The following four pairs of properties and methods should be called in the // order listed. // Specify and retrieve the source rowset from which data will be read. STDMETHOD(SetSourceRowset)(THIS_ DP_IN IRowset *pSrcRowset ) PURE; STDMETHOD(GetSourceRowset)(THIS_ DP_OUT IRowset **ppSrcRowset ) PURE; // Specify and retrieve the destination session and column schema; this defines how the // parameters to the queries will be bound. Specifying the schema is done in one of two ways: // - If cColumnDescs is 0, then rgColumnDescs is ignored and pDestConnection must // be a Rowset. Rowset information will be retrieved, but the Rowset itself will not // be retained. The Session will be retrieved from the Rowset and retained. // - If cColumnDescs is not 0, then rgColumnDescs must not be NULL and pDestConnection // must be a Session. The destination column definitions are created from the DBCOLUMNDESCs. // STDMETHOD(SetDestinationInfo)(THIS_ DP_IN IUnknown *pDestConnection, DP_IN ULONG cColumnDescs, DP_IN DBCOLUMNDESC rgColumnDescs[] ) PURE; // pcColumns, prgInfo, and ppStringsBuffer are allocated as in IColumnsInfo::GetColumnInfo. STDMETHOD(GetDestinationInfo)(THIS_ DP_IN REFIID riidSession, DP_OUT IUnknown **ppIUnkSession, DP_OUT ULONG *pcColumns, DP_OUT DBCOLUMNINFO **prgInfo, DP_OUT OLECHAR **ppStringsBuffer ) PURE; // Specify and retrieve the destination queries and their column mappings to parameters. // Unused queries may be NULL, in which case a Transform return status of DTSTransformStat_*Query // indicating an unset query will result in an error. STDMETHOD(SetDestinationQueries)(THIS_ DP_IN LPCDTSTransformQuerySpecification pInsertQuerySpec, DP_IN LPCDTSTransformQuerySpecification pUpdateQuerySpec, DP_IN LPCDTSTransformQuerySpecification pDeleteQuerySpec, DP_IN LPCDTSTransformQuerySpecification pUserQuerySpec ) PURE; // Each pointer is a single CoTaskMemAlloc containing space for the base QuerySpecification structure, // the array of column info, and the string buffer. Internal pointers are based (with alignment) // according to this allocated space. STDMETHOD(GetDestinationQueries)(THIS_ DP_OUT LPDTSTransformQuerySpecification *ppInsertQuerySpec, DP_OUT LPDTSTransformQuerySpecification *ppUpdateQuerySpec, DP_OUT LPDTSTransformQuerySpecification *ppDeleteQuerySpec, DP_OUT LPDTSTransformQuerySpecification *ppUserQuerySpec ) PURE; }; /////////////////////////////////////// // IDTSDataPumpLookups - Allows specification of Lookups for TransformServer use. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpSpecifyLookups DECLARE_INTERFACE_(IDTSDataPumpSpecifyLookups, IUnknown) { DTSDataPump_Unknown_Base() // Specify and retrieve the lookup specifications for this DataPump instance. STDMETHOD(SetLookups)(THIS_ DP_IN ULONG cLookups, DP_IN LPCDTSTransformLookupSpecification pLookups ) PURE; // The pointer is a single CoTaskMemAlloc containing space for the base LookupSpecification structure // and the string buffer. Internal pointers are based (with alignment) according to this allocated space. // pIUnkSession is AddRef'd and must be released. STDMETHOD(GetLookups)(THIS_ DP_IN ULONG *pcLookups, DP_IN LPDTSTransformLookupSpecification *ppLookups ) PURE; }; /////////////////////////////////////// // IDTSDataConvert - The DTS data-conversion interface. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataConvert DECLARE_INTERFACE_(IDTSDataConvert, IDataConvert) { DTSDataPump_Unknown_Base() ////////////////////////////////////////////////////// // IDataConvert interface members (msdadc.h required). ////////////////////////////////////////////////////// // Copies or converts data from one DBTYPE to another. If wDstType includes DBTYPE_BYREF, // it must be a variable-length type (DBTYPE_((W)STR|BYTES)) or this method will error. // Otherwise, for all DBTYPE_BYREF destination conversions, this method CoTaskMemAlloc(s) // the destination data pointer, and it is the caller's responsibility to CoTaskMemFree it. // This method should not be used to place data into the DataPump's destination binding; // instead, use the ConvertToBinding method. STDMETHOD(DataConvert)( DP_IN DBTYPE wSrcType, DP_IN DBTYPE wDstType, DP_IN ULONG cbSrcLength, DP_INOUT ULONG *pcbDstLength, DP_IN void *pSrc, DP_OUT void *pDst, DP_IN ULONG cbDstMaxLength, DP_IN DBSTATUS dbsSrcStatus, DP_OUT DBSTATUS *pdbsStatus, DP_IN BYTE bPrecision, DP_IN BYTE bScale, DP_IN DBDATACONVERT dwFlags ) PURE; // Determines if two types are potentially compatible. See GetConvertFlags // for more detailed information about what the conversion may encounter. STDMETHOD(CanConvert)( DP_IN DBTYPE wSrcType, DP_IN DBTYPE wDstType ) PURE; // Returns the required conversion size in bytes. May base this on pcbSrcLength // and/or pSrc, if supplied, to get per-data-item information. // // DBTYPE_BSTR is considered a fixed type; its binding length is sizeof(BSTR). // To determine the length necessary to pre-allocate a BSTR, pass in DBTYPE_STR // for the destination type - for this type, character count == byte count. // Alternatively, use WSTR and divide the return by sizeof(WCHAR). // STDMETHOD(GetConversionSize)( DP_IN DBTYPE wSrcType, DP_IN DBTYPE wDstType, DP_IN ULONG *pcbSrcLength, DP_OUT ULONG *pcbDstLength, DP_IN void *pSrc ) PURE; ////////////////////////////////////////////////////// // DTS extensions. ////////////////////////////////////////////////////// // This method first calls CanConvert() to determine if the conversion can succeed at all // given the source and destination datatypes, and if so, returns extended information about // how (or if) the conversion can proceed after that. // It uses the following fields for source and destination (S and D): // DBCOLUMNINFO - validates all conversion info between columns. // dwFlags S,D // ulColumnSize S,D // wType S,D // bPrecision S,D // bScale S,D // Fields other than dwFlags and wType can be zero'd and the output ConvertFlags // tested for the Unsupported bit if length validation is not required. // Note that this does not set a flag for nontext <-> text if the text length is // sufficient to accommodate it; this is because all such conversions should be valid // If this level of exactness is required, simply compare the datatypes for equality. STDMETHOD(GetConvertFlags)( DP_IN const DBCOLUMNINFO *pSrcColumnInfo, // Source column metadata DP_IN const DBCOLUMNINFO *pDestColumnInfo, // Destination column metadata DP_OUT DTSConvertFlags *pConvertFlags // Output conversion flags ) PURE; // This method allows the Transform Server to convert source data (which may come from // the source binding directly, as in the comment examples, or from ad-hoc source data). // It uses the following fields in the destination binding (S is fields that are used // from a source binding if that is how the source data is stored): // DBBINDING: // obValue S,D -- must be bound // obLength S,D -- must be bound // obStatus S,D -- must be bound // dwPart S,D -- must include length, value, status // cbMaxLen D // wType S,D // bPrecision D // bScale D // // The destination data is set according to eTransformFlags and pDestBind->dwMemOwner, which // is handled as follows: // // DBMEMOWNER_CLIENTOWNED: normal conversion is done; data is copied from source to destination, // converted as needed, and allocations are done as needed. Specifically: // BSTR data is deep-copied // BYREF destination data is copied into a CoTaskMemAlloc()'d pointer. // IUnknown and IDispatch pointers are AddRef()'d. // The destination binding data must always be free'd. The foregoing lists what is freed // (or Release()'d) by IDTSDataConvert::ClearBindingData. // // DBMEMOWNER_PROVIDEROWNED: Conversion will attempt to shallow-copy data, avoiding allocations. // This requires that the source and destination datatypes be identical (except for DBTYPE_BYREF). // This is intended as a performance enhancement and requires that the source data remain stable // for the lifetime of the Destination binding (such as while being inserted via the DataPump). // It handles only the following cases: // If the destination type includes DBTYPE_BYREF // it must therefore be ((W)STR|BYTES) // *pvDestData = pvSrcData (or *pvSrcData if source type is BYREF) // StringTruncation is performed by adjusting destination datalength // else if destination type is BSTR // *pvDestData = *pvSrcData (or **pvSrcData if source type is BYREF) // StringTruncation is NOT checked here as this is a fixed-length datatype // else // Normal conversion is done, including: // AddRefs of IDispatch/IUnknown pointers // VariantCopy (OLEDB behaviour does not allow PROVIDEROWNED Variant binding). // DBMEMOWNER_PROVIDEROWNED binding data will not be freed by IDTSDataConvert::ClearBindingData. // If a custom allocator is used for BYREF destination data, then it must be freed by a corresponding // custom deallocator, rather than by ClearBindingData. Therefore, it should be bound ProviderOwned; // the pointer will be shallow-copied into the binding by IDTSDataConvert::ConvertToBinding. // STDMETHOD(ConvertToBinding)( DP_IN DBTYPE wSrcType, // Source datatype: e.g. pSrcBind->wType DP_IN ULONG cbSrcLength, // Source data length: e.g. *(reinterpret_cast(pSrcColumnInfo->pvRowData + pSrcBind->obLength)); DP_IN DBSTATUS dbsSrcStatus, // Source data status: e.g. *(reinterpret_cast(pSrcColumnInfo->pvRowData + pSrcBind->obStatus)); DP_IN const BYTE *pvSrcColData, // Source column data: e.g. pSrcColumnInfo->pvRowData + pSrcBind->obValue; DP_IN const DBBINDING *pDestBind, // Dest binding info DP_IN BYTE *pvDestRowData, // Dest row data; NOT obValue-offset as the Binding will reference it 3 ways (obLength, obValue, obStatus) DP_IN DBCOLUMNFLAGS dwDestColumnFlags, // Dest flags such as nullability DP_IN ULONG ulDestColumnSize, // If nonzero and Dest is BYREF, tested for String Truncation DP_IN DTSTransformFlags eTransformFlags // Transformation flags. Currently considered: // DTSTransformFlag_AllowStringTruncation // DTSTransformFlag_ForceConvert as it applies to foregoing ) PURE; // This method frees any CLIENTOWNED allocations in the Binding, as discussed in ConvertToBinding. // This method always sets length to 0 and status to DBSTATUS_S_ISNULL, and can zeroinit if specified. STDMETHOD(ClearBindingData)( DP_IN const DBBINDING *pDestBind, // Dest binding info DP_IN BYTE *pvDestRowData, // Dest row data; NOT obValue-offset as the Binding will reference it 3 ways (obLength, obValue, obStatus) DP_IN BOOL bZeroInit // If TRUE, zero's the data value ) PURE; }; /////////////////////////////////////// // IDTSErrorRecords - Allows the caller to append OLEDB Error Records to the current // thread's IErrorInfo. The Error Lookup Service is CLSID_DTSErrorLookup. // This interface is derived from IDispatch and may be used in ActiveX Scripts as // well as from C/C++. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSErrorRecords DECLARE_INTERFACE_(IDTSErrorRecords, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSErrorRecords) STDMETHOD(Clear)(THIS) PURE; STDMETHOD(Add)(THIS_ DP_IN long Number, DP_IN long NativeError, DP_IN BSTR Description, DP_IN BSTR Source, DP_IN BSTR Helpfile, DP_IN long Helpid ) PURE; }; /////////////////////////////////////// // IDTSDataPumpColumns - Columns collection as exposed to AxScript. // We expose DTSSource and DTSDestination collections. // This interface is derived from IDispatch and may be used in ActiveX Scripts as // well as from C/C++. This is identical to the ADO.Field interface. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpColumns DECLARE_INTERFACE_(IDTSDataPumpColumns, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSDataPumpColumns) STDMETHOD(Item)(THIS_ DP_IN VARIANT Index, DP_OUT IDTSDataPumpColumn **pRetVal) PURE; STDMETHOD(get__NewEnum)(THIS_ DP_OUT IUnknown **ppEnum) PURE; STDMETHOD(get_Count)(THIS_ DP_OUT long *pRetVal) PURE; }; /////////////////////////////////////// // IDTSDataPumpColumn - Column object as exposed to AxScript. // These objects make up the DTSSource and DTSDestination collections. // They provide access to the column value and its metadata // This interface is derived from IDispatch and may be used in ActiveX Scripts as // well as from C/C++. This is identical to the ADO.Field interface. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpColumn DECLARE_INTERFACE_(IDTSDataPumpColumn, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSDataPumpColumn) STDMETHOD(get_Value)(THIS_ DP_OUT VARIANT *pRetVal) PURE; STDMETHOD(put_Value)(THIS_ DP_IN VARIANT NewValue) PURE; STDMETHOD(get_ActualSize)(THIS_ DP_OUT long *pl) PURE; STDMETHOD(get_Attributes)(THIS_ DP_OUT long *pl) PURE; STDMETHOD(get_DefinedSize)(THIS_ DP_OUT long *pl) PURE; STDMETHOD(get_Name)(THIS_ DP_OUT BSTR *pbstr) PURE; STDMETHOD(get_Type)(THIS_ DP_OUT long *pDataType) PURE; STDMETHOD(get_Precision)(THIS_ DP_OUT BYTE *pbPrecision) PURE; STDMETHOD(get_NumericScale)(THIS_ DP_OUT BYTE *pbNumericScale) PURE; STDMETHOD(get_OriginalValue)(THIS_ DP_OUT VARIANT *pvar) PURE; STDMETHOD(get_UnderlyingValue)(THIS_ DP_OUT VARIANT *pvar) PURE; STDMETHOD(AppendChunk)(THIS_ DP_IN VARIANT Data) PURE; STDMETHOD(GetChunk)(THIS_ DP_IN long Length, DP_OUT VARIANT *pvar) PURE; }; /////////////////////////////////////// // IDTSDataPumpLookups - Lookups collection as exposed to AxScript. // We expose DTSLookups as a collection. // This interface is derived from IDispatch and may be used in ActiveX Scripts as // well as from C/C++. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpLookups DECLARE_INTERFACE_(IDTSDataPumpLookups, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSDataPumpLookups) STDMETHOD(Item)(THIS_ DP_IN VARIANT Index, DP_OUT IDTSDataPumpLookup **pRetVal) PURE; STDMETHOD(Get_NewEnum)(THIS_ DP_OUT IUnknown **ppEnum) PURE; STDMETHOD(GetCount)(THIS_ DP_OUT long *pRetVal) PURE; }; /////////////////////////////////////// // IDTSDataPumpLookup - Lookup object as exposed to AxScript. // These objects make up the DTSLookups collection. // This interface is derived from IDispatch and may be used in ActiveX Scripts as // well as from C/C++. The KeyValues input parameter to the methods is a SafeArray // of Variant, using the vararg attribute on the methods, for best use in ActiveX // scripts. The return value is a variant (if single-valued) or an array of variants // (if multi-valued) corresponding to the sequence of columns in the single output // row resulting from execution of the query. If multiple rows are returned, only // the first is returned in the output variant. LastRowCount is used in case an // app wants to assert that only one row was returned. /////////////////////////////////////// // This form is understood by scripting languages to take a variable number of // arguments in the key values specification. It can be used from C++ as well. #undef INTERFACE #define INTERFACE IDTSDataPumpLookup DECLARE_INTERFACE_(IDTSDataPumpLookup, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSDataPumpLookup) STDMETHOD(get_Name)(THIS_ DP_OUT BSTR *pbstr) PURE; STDMETHOD(get_LastRowCount)(THIS_ LONG *pRetVal) PURE; STDMETHOD(Execute)(THIS_ DP_IN SAFEARRAY * KeyValues, DP_OUT VARIANT *pRetVal) PURE; STDMETHOD(AddToCache)(THIS_ DP_IN VARIANT DataValues, DP_IN SAFEARRAY * KeyValues) PURE; STDMETHOD(RemoveFromCache)(THIS_ DP_IN SAFEARRAY * KeyValues) PURE; }; // This is a form of the interface which takes a single Variant, more convenient // for C++ programs which know they'll only have a single key column. The variant // may be a single value or may itself contain a safearray. #undef INTERFACE #define INTERFACE IDTSDataPumpLookupVariant DECLARE_INTERFACE_(IDTSDataPumpLookupVariant, IUnknown) { STDMETHOD(Execute)(THIS_ DP_IN VARIANT KeyValues, DP_OUT VARIANT *pRetVal) PURE; STDMETHOD(AddToCache)(THIS_ DP_IN VARIANT DataValues, DP_IN VARIANT KeyValues) PURE; STDMETHOD(RemoveFromCache)(THIS_ DP_IN VARIANT KeyValues) PURE; }; //////////////////////////////////////////////////////////////////////////////////////// // // Pump-supplied Transform custom-property interfaces. // //////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////// // IDTSDataPumpTransformScriptProperties - Sets custom properties for the // ActiveX scripting transformation server. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpTransformScriptProperties DECLARE_INTERFACE_(IDTSDataPumpTransformScriptProperties, DTSDataPump_IDispatch) { DTSDataPump_Dispatch_Base(IDTSDataPumpTransformScriptProperties) STDMETHOD(GetText)(THIS_ BSTR DP_OUT *pRetVal) PURE; STDMETHOD(SetText)(THIS_ BSTR DP_IN NewValue) PURE; STDMETHOD(GetLanguage)(THIS_ BSTR DP_OUT *pRetVal) PURE; STDMETHOD(SetLanguage)(THIS_ BSTR DP_IN NewValue) PURE; STDMETHOD(GetFunctionEntry)(THIS_ BSTR DP_OUT *pRetVal) PURE; STDMETHOD(SetFunctionEntry)(THIS_ BSTR DP_IN NewValue) PURE; }; //////////////////////////////////////////////////////////////////////////////////////// // // Consumer-supplied interface definitions. // //////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////// // IDTSDataPumpTransform - Required interface of the "COM Server" instantiated by ServerClsid // passed to IDTSDataPump::AddTransform. This interface is retrieved and its methods called // by the Pump to perform individual transforms. // // ServerParameters allows the DataPump Consumer to instantiate a single instance of an // IDTSDataPumpTransform implementation and pass it to multiple IDTSDataPump::AddTransform calls. // This is only useful for custom Transform Servers (the DTS-supplied ones ignore this), and may be // helpful for internal summations etc. If this is done, the TransformServer should track this in its // pvTransformServerData to optimize operations such as AddVariable, On(Row|Transform)Complete, etc. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpTransform DECLARE_INTERFACE_(IDTSDataPumpTransform, IUnknown) { DTSDataPump_Unknown_Base() // Allows the TransformServer to initialize its state for the current Transform. The output // LPBYTE is passed to all subsequent methods, so a single TransformServer instance may be // used to implement multiple separate transforms. STDMETHOD(Initialize)(THIS_ DP_IN LPCOLESTR pwzName, // Transform name DP_IN VARIANT ServerParameters, // Parameters to server for this transform DP_OUT LPBYTE *ppvTransformServerData // Transform server state data. ) PURE; // Validates the schema that will be transformed. Allows the TransformServer to specify // certain modifications to the default binding modes, such as for BLOBs. The default // p(Src|Dest)ColumnInfo->ppDTSColBinding[ii].eBindModes intialized by the DataPump are: // // All BLOBs must be ClientOwned by OLEDB spec, so Source and Destination BLOBs are always // DTSBindMode_Byref_ClientOwned. // // Source: For efficiency, nonBLOB ((W)STR|BYTES) binding defaults to _Byref_ProviderOwned // to avoid unnecessary copying. BSTR defaults to ProviderOwned. All other types must be // non-Byref ClientOwned by OLEDB spec and behaviour. // // Destination: Because the destination data is likely to be the result of a transformation, // destination binding always defaults to ClientOwned for all datatypes. All nonBLOB types are // allocated Inline; this includes ((W)STR|BYTES), to minimize per-row (re)allocation overhead. // // A Transformation which simply passes-thru nonBLOB ((W)STR|BYTES)s or BSTRs from the Source // IRowset to the destination (and doesn't use the TransformCopy server, which is supplied for // this purpose) should override this to ProviderOwned to avoid unnecessary (re)allocations. // STDMETHOD(ValidateSchema)(THIS_ DP_IN LPBYTE pvTransformServerData, // Transform server state data. DP_INOUT LPCDTSTransformColumnInfo pSrcColumnInfo, // Source columns and rowdata DP_INOUT LPCDTSTransformColumnInfo pDestColumnInfo, // Dest columns and rowdata DP_IN IDTSDataConvert *pIDTSDataConvert, // Pointer to the data conversion interface DP_IN DTSTransformFlags eTransformFlags // Input Flags for Transformation validation and execution ) PURE; // Adds a variable to the TransformServer's execution context. This is always called once before // ValidateSchema, in order to add the IDTSErrorRecords object. STDMETHOD(AddVariable)(THIS_ DP_IN LPBYTE pvTransformServerData, // Transform server state data. DP_IN LPCOLESTR pwzName, // Variable name DP_IN BOOL bGlobal, // For ActiveX scripts, indicates whether this variable's // methods must be qualified by the object name. DP_IN VARIANT Variable // Variable value; passed to and updatable by Transform ) PURE; // Executes the transformation for a single row. This method should return a SUCCEED // hr except in catastrophic failure; a FAILED hr here will abort the Pump. "Normal" // errors such as data violations should be handled as a returned pTransformStatus, // which will cause IDTSDataPumpErrorSink::OnTransformError to be called. // // Because some providers may have restrictions on the number of Storage Objects which // may be open, Execute() should release any Blob Storage Objects in the source upon // completion, rather than waiting for OnRowComplete. The DataPump handles refcounting // for multiple transforms of its buffered Source objects. If the Blob column is // buffered by the DataPump or the Transform has knowledge of the Source Provider, it // can defer Release()ing the Source Storage Object until OnRowComplete. Note that // returning DTSTransformStat_SkipFetch (and therefore not releasing the Source Storage // Object) may require buffering of the source Blob data. STDMETHOD(Execute)(THIS_ DP_IN LPBYTE pvTransformServerData, // Transform server state data. DP_IN LPCDTSTransformColumnInfo pSrcColumnInfo, // Source columns and rowdata DP_INOUT LPDTSTransformColumnInfo pDestColumnInfo, // Dest columns and rowdata DP_IN IDTSDataConvert *pIDTSDataConvert, // Pointer to the data conversion interface DP_OUT LPDTSTransformStatus peTransformStatus // Result of transform ) PURE; // After a successful Fetch, the pump calls Execute and then attempts to insert the row into the // destination IRowsetChange (if one is specified). OnRowComplete is called for every successful // Fetch (whether the Execute() and InsertRow succeeded or failed); this allows the TransformServer // to free per-row allocations and CLIENTOWNED data in both source and destination rows (such as // by calling pIDTSDataConvert->ClearBindingData). A FAILED return from OnRowComplete aborts the Pump. // hrInsert indicates whether the IRowsetChange::InsertRow() succeeded; eTransformStatus indicates // if errors occurred such that InsertRow was not called. // // Note that OLEDB specifies that IRowsetChange::InsertRow() Releases any contained Storage Objects // in the row (but not other types of "allocations"), so the Transform server must be careful not to // call pIDTSDataConvert->ClearBindingData on an already final-released Storage Object (in the event // that InsertRow is not called due to a Transform returning an error, the DataPump will release any // Storage Objects in the dest row for any Transforms for which Execute was called prior to the erroring // Transform, to present a consistent refcounting interface to TransformServers: If Execute() returned // a non-NULL Storage Object in the row, it will be released once before OnRowComplete is called). // STDMETHOD(OnRowComplete)(THIS_ DP_IN LPBYTE pvTransformServerData, // Transform server state data. DP_INOUT LPDTSTransformColumnInfo pSrcColumnInfo, // Source columns and rowdata DP_INOUT LPDTSTransformColumnInfo pDestColumnInfo, // Dest columns and rowdata DP_IN IDTSDataConvert *pIDTSDataConvert, // Pointer to the data conversion interface DP_IN DTSTransformStatus eTransformStatus, // Result of Execute() DP_IN HRESULT hrInsert // Result of IRowsetChange::InsertRow() ) PURE; // After all rows have been transformed (or the pump has been shutdown due to errors), // OnTransformComplete is called to give the TransformServer a chance to clean up all // allocations made for the Transform. OnTransformComplete is called only if ValidateSchema // returned successfully. STDMETHOD(OnTransformComplete)(THIS_ DP_IN LPBYTE pvTransformServerData, // Transform server state data. DP_INOUT LPDTSTransformColumnInfo pSrcColumnInfo, // Source columns and rowdata DP_INOUT LPDTSTransformColumnInfo pDestColumnInfo, // Dest columns and rowdata DP_IN IDTSDataConvert *pIDTSDataConvert // Pointer to the data conversion interface ) PURE; }; /////////////////////////////////////// // IDTSDataPumpErrorSink - Specifies pump error handler sink. Only one method will // be called for any row, and the method called indicates where the error was encountered: // reading from source, transforming, or writing to destination. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpErrorSink DECLARE_INTERFACE_(IDTSDataPumpErrorSink, IUnknown) { DTSDataPump_Unknown_Base() // An error occurred on Binding in CreateAccessor. This is only useful for designing custom Transform // Servers, primarily for diagnosing Blob difficulties. STDMETHOD(OnBindingError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN HRESULT hrError, // The errorcode from CreateAccessor; for Destination if pDestinationRow, else for Source. DP_IN LPCDTSTransformColumnInfo pSourceRow, // Pointer to the source row and binding info. DP_IN const DBBINDSTATUS *pSourceDBBindStatus, // Pointer to source binding status returns. DP_IN LPCDTSTransformColumnInfo pDestinationRow, // Pointer to the destination row and binding info; NULL if from Source Binding error. DP_IN const DBBINDSTATUS *pDestinationDBBindStatus // Pointer to destination binding status returns; NULL if from Source Binding error. ) PURE; // An error occurred during GetNextRows or GetData. STDMETHOD(OnSourceError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN LPDTSTransformColumnInfo pSourceRow, // Pointer to the source row and binding info; NULL if GetNextRows or GetData failed. DP_IN HRESULT hrError, // The errorcode from the OLEDB or system call. DP_IN ULARGE_INTEGER uliRow, // Number of the row failing. DP_IN ULONG cErrors, // Number of error rows encountered so far (including this one). DP_OUT BOOL *pbAbort // Set TRUE by Sink if this error should abort IDTSDataPump::Execute. // Otherwise, Execute() continues until MaximumErrorRowCount is exceeded. ) PURE; // An error occurred on one or more Transforms. STDMETHOD(OnTransformError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN LPCOLESTR pwzName, // Transform name DP_IN LPBYTE pvTransformUserData, // User data pointer passed to IDTSDataPump::AddTransform // in LPCDTSTransformColumnsSpecification parameter. DP_IN IDTSDataPumpTransform *pTransformServer, // The transform server raising the error; can be QI'd to custom interface for more info. DP_IN LPDTSTransformColumnInfo pSourceRow, // Pointer to the source row and binding info. DP_IN DTSTransformStatus TransformStatus, // Returned status code from the transformation. DP_IN HRESULT hrTransform, // The HRESULT returned from DTSDataPumpTransform::Execute. DP_IN ULARGE_INTEGER uliRow, // Number of the row failing. DP_IN ULONG cErrors, // Number of error rows encountered so far (including this one). DP_OUT BOOL *pbAbort // Set TRUE by Sink if this error should abort IDTSDataPump::Execute. // Otherwise, Execute() continues until MaximumErrorRowCount is exceeded. ) PURE; // An error occurred during InsertRow. STDMETHOD(OnDestinationError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN LPDTSTransformColumnInfo pSourceRow, // Pointer to the source row. DP_IN LPDTSTransformColumnInfo pDestinationRow, // Pointer to the destination row and binding info; NULL if prior to transform execution. DP_IN HRESULT hrError, // The errorcode from the OLEDB or system call. DP_IN ULARGE_INTEGER uliRow, // Number of the row failing. DP_IN ULONG cErrors, // Number of error rows encountered so far (including this one). DP_OUT BOOL *pbAbort // Set TRUE by Sink if this error should abort IDTSDataPump::Execute. // Otherwise, Execute() continues until MaximumErrorRowCount is exceeded. ) PURE; }; /////////////////////////////////////// // IDTSDataDrivenQuerySink - Specifies event sink for Data Driven Queries. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataDrivenQuerySink DECLARE_INTERFACE_(IDTSDataDrivenQuerySink, IUnknown) { DTSDataPump_Unknown_Base() STDMETHOD(OnDDQBindingError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN DTSTransformStatus fQueryType, // Insert, Update, Delete, or User Query. DP_IN HRESULT hrError, // The errorcode from CreateAccessor for Command parameters DP_IN LPCDTSTransformColumnInfo pDestinationRow, // Pointer to the destination row and transform binding info DP_IN ULONG cParameterColumns, // Number of parameter columns DP_IN const DBBINDING *pParameterDBBinding, // Pointer to destination parameter bindings DP_IN const DBBINDSTATUS *pParameterDBBindStatus // Pointer to destination parameter binding status returns ) PURE; STDMETHOD(OnDDQCommandError)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN DTSTransformStatus fQueryType, // Insert, Update, Delete, or User Query. DP_IN LPDTSTransformColumnInfo pSourceRow, // Pointer to the source row. DP_IN LPDTSTransformColumnInfo pDestinationRow, // Pointer to the destination row and binding info. DP_IN HRESULT hrError, // The errorcode from the OLEDB or system call. DP_IN ULARGE_INTEGER uliRow, // Number of the row failing. DP_IN ULONG cErrors, // Number of error rows encountered so far (including this one). DP_OUT BOOL *pbAbort // Set TRUE by Sink if this error should abort IDTSDataPump::Execute. // Otherwise, Execute() continues until MaximumErrorRowCount is exceeded. ) PURE; STDMETHOD(OnDDQCommandComplete)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN DTSTransformStatus fQueryType, // Insert, Update, Delete, or User Query. DP_IN LPDTSTransformColumnInfo pSourceRow, // Pointer to the source row. DP_IN LPDTSTransformColumnInfo pDestinationRow, // Pointer to the destination row and binding info. DP_IN LONG cDestinationRowsAffected, // Rows affected by Command; -1 if provider unable to determine. DP_IN ULARGE_INTEGER uliRow // Number of the source row for which the Query was Execute()d. ) PURE; }; /////////////////////////////////////// // IDTSCustomTransformUI - // optional interface to be implemented by custom transform providers - used by DTS UI to configure the transforms /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSCustomTransformUI DECLARE_INTERFACE_(IDTSCustomTransformUI, IUnknown) { DTSDataPump_Unknown_Base() STDMETHOD(Initialize)(THIS_ DP_IN LPUNKNOWN pDTSPkgTransformObject) PURE; STDMETHOD(New)(THIS_ DP_IN long hwndParent) PURE; STDMETHOD(Edit)(THIS_ DP_IN long hwndParent) PURE; STDMETHOD(Delete)(THIS_ DP_IN long hwndParent) PURE; STDMETHOD(Help)(THIS_ DP_IN long hwndParent) PURE; }; /////////////////////////////////////// // IDTSDataPumpProgressSink - Progress indicator event sink. /////////////////////////////////////// #undef INTERFACE #define INTERFACE IDTSDataPumpProgressSink DECLARE_INTERFACE_(IDTSDataPumpProgressSink, IUnknown) { DTSDataPump_Unknown_Base() STDMETHOD(OnIntervalComplete)(THIS_ DP_IN LPBYTE pvExecUserData, // User data pointer passed to IDTSDataPump::Execute DP_IN ULARGE_INTEGER uliRowsComplete, // Total Source Rows processed at this interval (includes those skipped) DP_OUT BOOL *pbAbort // Set TRUE by Sink to abort IDTSDataPump::Execute. ) PURE; }; ///////////////////////////////////////////////////////////////////////////////// // DTS Repository-support interfaces. ///////////////////////////////////////////////////////////////////////////////// // Repository interfaces and definitions are shared between DTSDataPump and DTSPackage. #ifdef OBJID_DtsTransformationTask // A covering utility interface around a Repository object, provided by the DTS Package // when requesting repository storage from a custom Task or Transformation. This interface // is passed to IDTSRepositoryStorage methods during DTSPackage.SaveToRepository. #undef INTERFACE #define INTERFACE IDTSRepositoryProvider DECLARE_INTERFACE_(INTERFACE, IUnknown) { DTSDataPump_Unknown_Base() // Return a reference to the Repository object. STDMETHOD(GetRepository)(THIS_ DP_OUT IRepository **ppIRepository // The repository object. ) PURE; // Creates an object and sets its name. STDMETHOD(CreateObject)(THIS_ DP_IN LPCOLESTR wzObjidClass // Repository class to create , DP_IN LPCOLESTR wzObjidInstance // class instance (object) id, or NULL , DP_IN LPCOLESTR wzInstanceName // class instance (object) name, or NULL , DP_OUT IRepositoryObject **ppRepositoryObject // created object ) PURE; // Finds an IDbmConnection object for a DTS connection in the associated DTS Package. STDMETHOD(FindConnection)(THIS_ DP_IN LPCOLESTR wzName // DTSConnection.Name , DP_IN long lID // DTSConnection.ID , DP_OUT IRepositoryDispatch **ppIDbmConnection // output object ) PURE; // When a custom Task or Transformation references a table or view, it should create a // relationship to that table or view if the appropriate datasource and catalog's metadata // has been scanned (by dbscanner) into the Repository. To do so, the IDTSRepositoryStorage // implementation should call FindScannedObject, passing the name of the table or view // to be referenced. Note that this name should be qualified as necessary to resolve // ambiguity, if multi-part names are supported by the connection provider. This qualification // must be done according to DBPROP_CATALOGUSAGE and DBPROP_SCHEMAUSAGE, and the following // DBLITERALs: // DBLITERAL_QUOTE_PREFIX // DBLITERAL_QUOTE_SUFFIX // DBLITERAL_CATALOG_SEPARATOR // DBLITERAL_SCHEMA_SEPARATOR // // DTSPackage.SaveToRepository will search for a scanned catalog contained within any // IDbmDataSource with IsPublic TRUE. A table or view resides in the repository as follows: // Root(IUmlPackage).Elements // ... possibly some intervening level of package or system... // IDbmDataSource(IUmlPackage).Elements // IDbmDeployedCatalog(IUmlPackage).Elements // IDbmSchema(IUmlPackage).Elements // IDbmDeployedTable, IDbmDeployedView // The catalog in which wzObjectName is resolved is determined by the first name found in // the following order: // A catalog name parsed from wzObjectName // DBPROP_CURRENTCATALOG after IDTSConnection.OpenConnection; this may be set by either of: // IDTSConnection.DefaultCatalog // IDTSConnection.ConnectionProperties(DBPROP_INIT_CATALOG) // If DBPROP_CURRENTCATALOG is not supported, a placeholder catalog is // created by the scanner; this catalog is used to resolve scanned object references. // // The schema in which wzObjectName is resolved is determined by the first name found in // the following order: // A schema name parsed from wzObjectName // IDTSConnection.UserID // IDTSConnection.ConnectionProperties(DBPROP_AUTH_USERID) // // Because the connection's UserID may be simply a login id and different from the actual // object owner, wzObjectName should be qualified. Only one schema will be searched for the // object; that schema is determined by: // If a Schema-qualified wzObjectName is passed, that Schema is searched. // Else if only one Schema is specified, it is searched. // Else if a UserID is specified, it is used. // Else EREP_OBJ_NOTFOUND. // // FindScannedObject returns the following, in order: // If the call to DTSPackage.SaveToRepository specified that no scanner resolution be done, // FindScannedObject returns NULL and S_FALSE. In this case, AddUnscannedObject should be // called, to create an DTSPackage-level object for AddTransformationUses to relate to. // // If the provider does not support SchemaRowsets (necessary for scan), FindScannedObject // returns NULL and S_FALSE. // // If the catalog has not been scanned, or if the call to DTSPackage.SaveToRepository // specified to rescan, then the catalog is scanned. Any error from the dbscanner (such as // the catalog not being found) is returned. // // If wzObjectName is not found, EREP_OBJ_NOTFOUND is returned. // // If wzObjectName is not found uniquely, such as an unqualified name appearing in more than // one schema, EREP_OBJ_NOTFOUND is returned. // // If wzObjectName is found uniquely, the IDbmDeployedTable or IDbmDeployedView is placed in // ppIScannedObject and S_OK is returned. // // Note that FindScannedObject should not be called for an IDbmQuery object, as these are not // scanned into the repository as part of a Catalog; they are owned by the connection consumer. // IDbmQuery objects should be added via AddUnscannedObject. // // Generally a custom Task or Transformation will do the following (with most error handling omitted // for brevity): // pIRepositoryProvider->CreateObject(OBJID_MyCustomTaskOrTransform // , NULL // , wzObjectName // , &pICustomTaskOrTransform); // if (referencing a table or view) { // if FAILED(pIRepositoryProvider->FindScannedObject( // , IID_IRepositoryObject // , pIDbmConnection // , &pINewObject)) // return error; // } // if (NULL == pUnk) { // pIRepositoryProvider->CreateObject(, // , &pINewObject); // pIRepositoryProvider->AddUnscannedObject(pIDbmConnection // , pINewObject); // } // pIRepositoryProvider->AddTransformationUses(L"Source Table" // , pICustomTaskOrTransform // , pINewObject); // STDMETHOD(FindScannedObject)(THIS_ DP_IN LPCOLESTR wzObjectName // Name of the object (may be qualified by catalog.schema.name) , DP_IN REFIID iidToGet // an IID the object must support; ignored if IID_NULL , DP_IN IRepositoryDispatch *pIDbmConnection // Connection object (e.g. from FindConnection) , DP_OUT IRepositoryObject **ppIScannedObject // returns scanned object or NULL on error. ) PURE; // This method adds an object to the repository as a way for AddTransformationUses to form a // relationship. This object is not visible outside the scope of the saved DTSPackage. pINewObject // is created (e.g. by CreateObject) and may be a table or view, or query, or a specialization (derived // class) of one, according to the following mapping: // Object type Must support Added to // ----------- ------------ --------- // Query ITfmQuery ITfmTransformation(IUmlType).Members // ITfmTransformationTask(IUmlType).Members // Table IDbmDeployedTable Package-local DataSource/Catalog/Schema // View IDbmDeployedView Package-local DataSource/Catalog/Schema // other IUmlMember ITfmTransformation(IUmlType).Members // ITfmTransformationTask(IUmlType).Members // STDMETHOD(AddUnscannedObject)(THIS_ DP_IN IRepositoryDispatch *pIDbmConnection // Connection object (e.g. from FindConnection) , DP_IN IRepositoryObject *pINewObject // Task/Transform-created object. ) PURE; // This method creates a relationship between an ITfmTransformation or ITfmTransformationTask // and an IDbmColumnSet specialization (such as an IDbmDeployedTable, IDbmDeployedView, or ITfmQuery) // via the ITfmTransformationUses specialization of IUmlDependency, where // ITfmTransformationUses(IUmlDependency).SourceElement = pITaskOrTransform // ITfmTransformationUses(IUmlDependency).TargetElement = pINewObject // // Any dependencies added in this manner can be retrieved during LoadFromRepository by: // pITaskOrTransform(IID_IUmlElement).TargetDependencies // STDMETHOD(AddTransformationUses)(THIS_ DP_IN LPCOLESTR wzDependencyType // A string describing the dependency; e.g., L"Source Table". , DP_IN IRepositoryObject *pITaskOrTransform // Task/Transform-created object. , DP_IN IRepositoryObject *pINewObject // Task/Transform-created object. ) PURE; // Creates a datatype object which maps the passed DBTYPE and other information to // its Repository equivalent, and creates and returns a matching object. STDMETHOD(CreateMappedDatatypeObject)(THIS_ DP_IN DBTYPE dbType // The OLEDB datatype , DP_IN LONG lSize // Column size in characters (ignored if a fixed-length datatype) , DP_IN LONG lPrecision // Column precision if DECIMAL or NUMERIC , DP_IN LONG lScale // Column scale if DECIMAL or NUMERIC , DP_OUT IRepositoryObject **ppRepositoryObject // output object ) PURE; // Gets information from a datatype object created by CreateMappedDataTypeObject. STDMETHOD(GetMappedDatatypeInfo)(THIS_ DP_IN IRepositoryObject *pRepositoryObject // input object , DP_OUT DBTYPE *pdbType // The OLEDB datatype , DP_OUT LONG *plSize // Column size in characters (ignored if a fixed-length datatype) , DP_OUT LONG *plPrecision // Column precision if DECIMAL or NUMERIC , DP_OUT LONG *plScale // Column scale if DECIMAL or NUMERIC ) PURE; }; // If a custom task or custom transform server wants to manage its Repository persistence itself, // it must implement IDTSRepositoryStorage. Otherwise, the Package will simply enumerate the // OleAutomation properties of the custom task/transform IDispatch and store all those which // can be Set() as (Variant)TaggedValues of an IDtsCustomTask repository object. #undef INTERFACE #define INTERFACE IDTSRepositoryStorage DECLARE_INTERFACE_(INTERFACE, IUnknown) { DTSDataPump_Unknown_Base() // The implementation must create its own Repository object via pIRepositoryProvider->CreateObject, // and the returned ppIRepositoryObject must be fully populated and must support IDtsCustomTask // (if a custom DTSPackage Task) or IDts(Blob)Transformation (if a custom DTSPump Transform server). // After this method returns, the DTSPackage will set properties for Task Name via INamedObject::Name // and ServerID (the ProgID or string form of CLSID by which the custom task/transformation server is // CoCreateInstance()'d) and any other base-class values needed. Custom objects should not set tagged // values in the base object classes, to avoid possible name conflicts. STDMETHOD(SaveToRepository)(THIS_ DP_IN IDTSRepositoryProvider *pIRepositoryProvider , DP_OUT IRepositoryObject **ppIRepositoryObject ) PURE; // The implementation loads its own properties from this object. If access to the IRepository // object is necessary, use pIRepositoryObject->get_Repository(). STDMETHOD(LoadFromRepository)(THIS_ DP_IN IDTSRepositoryProvider *pIRepositoryProvider , DP_IN IRepositoryObject *pIRepositoryObject ) PURE; }; #endif // def OBJID_DtsTransformationTask #endif // ndef DTSDataPump_VersionOnly #endif // ndef DTSDataPump_ODL_ #pragma option pop /*P_O_Pop*/ #endif // DTSDataPump_H_