This repository has been archived on 2024-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
CodeBlocksPortable/Borland/BCC55/Include/dtspump.h

1850 lines
92 KiB
C
Raw Permalink Normal View History

//
// 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<6D>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:
// <nonchar> <--> 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<4F>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<4F>d into the following error returns.
DTSTransformExec_Error = 0x00001000, // Bit-or<6F>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:
// <T> - TransformFlag is available to explicitly allow this.
// <E> - Error may be encountered during Convert()
// <F> - 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)).
// <T>
DTSConvertFlag_Promotion = 0x00000001,
// Conversion will demote (e.g. I4 -> I2); overflow error possible.
// <T, E>
DTSConvertFlag_Demotion = 0x00000002,
// Conversion may do string or byte truncation; truncation error possible if
// this flag is not specified on Convert().
// <T, E>
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.
// <T>
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.
// <T, E>
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).
// <T, E>
DTSConvertFlag_SignChange = 0x00000020,
// Destination column size is too short for a meaningful conversion from source
// column type.
// <F>
DTSConvertFlag_DestTooShort = 0x00000040,
// Source column size is too short for a meaningful conversion to destination
// column type.
// <F>
DTSConvertFlag_SourceTooShort = 0x00000080,
// Source and destination datatypes are not really compatible, but conversion can be forced.
// <T>
DTSConvertFlag_ForceConvert = 0x00000100,
// Conversion fails because of bad or incompatible column types.
// <F>
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 <20>.<2E> in name)
// BYTE/LONG == guid encoding (e.g. Repository))
// UNKNOWN == pointer to IID_IDTSDataPumpTransform
LPOLESTR OleStr; // Progid or clsid (differentiated by looking for <20>.<2E> 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 <initguid.h> 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 <Custom OleAut properties interface>;
// 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<ULONG *>(pSrcColumnInfo->pvRowData + pSrcBind->obLength));
DP_IN DBSTATUS dbsSrcStatus, // Source data status: e.g. *(reinterpret_cast<DBSTATUS *>(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(<name>
// , IID_IRepositoryObject
// , pIDbmConnection
// , &pINewObject))
// return error;
// }
// if (NULL == pUnk) {
// pIRepositoryProvider->CreateObject(<parameters for the table, view, query, or other object>,
// , &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_