// New cotypes:
// Binder objects:
CoType TBinder {
[mandatory] interface IBindResource;
[mandatory] interface ICreateRow;
[mandatory] interface IDBBinderProperties;
[optional] interface IRegisterProvider; // Root binder only
[optional] interface ISupportErrorInfo;
}
// Row objects:
CoType TRow {
[mandatory] interface IColumnsInfo;
[mandatory] interface IConvertType;
[mandatory] interface IGetSession;
[mandatory] interface IRow;
[optional] interface IColumnsInfo2;
[optional] interface IConnectionPointContainer;
[optional] interface ICreateRow;
[optional] interface IDBAsynchStatus;
[optional] interface IDBCreateCommand;
[optional] interface IDBInitialize;
[optional] interface IRowChange;
[optional] interface IRowSchemaChange;
[optional] interface IScopedOperations;
[optional] interface ISupportErrorInfo;
}
// Stream objects:
CoType TStream {
[mandatory] interface ISequentialStream;
[optional] interface IConnectionPointContainer;
[optional] interface IDBAsynchStatus;
[optional] interface IDBInitialize;
[optional] interface IGetSourceRow;
[optional] interface ISupportErrorInfo;
[optional] interface IStream;
}
// New interfaces on existing objects:
// New interfaces on Session objects:
[optional] interface IBindResource;
[optional] interface ICreateRow;
// New interfaces on Rowset objects:
[optional] interface IColumnsInfo2;
[optional] interface IGetRow;
Figure 5 Getting a Row Object
HRESULT GetSam2(IOpenRowset *pSession,
IRow **ppRow)
{
// call OpenRowset passing URL for table name
// and asking for a rowset
DBID idTable;
idTable.eKind = DBKIND_NAME;
idTable.uName.pwszName = L"http://bob.com/sam.htm";
CComPtr<IRowset> pRowset;
// Error checking deleted for clarity.
pSession->OpenRowset(NULL, &idTable, NULL, IID_IRowset, 0, NULL,
(IUnknown **)&pRowset;
// get a ROW HANDLE for the first row
enum { ROWSTOGET = 1 };
ULONG ulRows;
HROW rghRows[ROWSTOGET];
pRowset->GetNextRows(NULL, 0, ROWSTOGET, &ulRows, rghRows);
CComPtr<IGetRow> pGetRow;
pRowset->QueryInterface(IID_IGetRow,
(void**)&pGetRow);
// use the ROW handle to get a Row object
return pGetRow->GetRowFromHROW(NULL, rghRows[0], IID_IRow,
(IUnknown **)ppRow);
Figure 6 DBCOLUMNACCESS Structure
typedef struct tagDBCOLUMNACCESS {
void * pData; // ptr to buffer for the data
DBID columnid; // column ID
ULONG cbDataLen; // returned data length
DBSTATUS dwStatus; // status field
ULONG cbMaxLen; // maximum length of the buffer
DWORD dwReserved; // MBZ
DBTYPE wType; // data type
BYTE bPrecision; // numeric precision
BYTE bScale; // numeric scale
} DBCOLUMNACCESS;
Figure 7 ColumnAccess
void createColumnAccess
(
ULONG nCols, // [in]
DBCOLUMNINFO* pColInfo, // [in]
OLECHAR* pColumnStrings, // [in]
DBCOLUMNACCESS** ppDBColAcc, // [out]
void** ppColData // [out]
)
{
ULONG i;
DBCOLUMNACCESS* pDBColAcc;
pDBColAcc = new DBCOLUMNACCESS[nCols];
ppColumnData = new void*[nCols];
for (i = 0; i < nCols; i++)
{
// need to add character for trailing null
// if this is a string column binding
ppColData[i] = new char[pColInfo[i].ulColumnSize];
pDBColAcc[i].pData = ppColData[i];
pDBColAcc[i].columnid =pColInfo[i].columnid;
pDBColAcc[i].cbDataLen = pColInfo[i].ulColumnSize;
pDBColAcc[i].cbMaxLen = pColInfo[i].ulColumnSize;
pDBColAcc[i].wType = pColInfo[i].wType;
pDBColAcc[i].bPrecision = pColInfo[i].bPrecision;
pDBColAcc[i].bScale = pColInfo[i].bScale;
}
*ppDBColAcc = pDBColAcc;
return;
}
Figure 8 Adding a Column
HRESULT AddAColumn(IRow *pr)
{
HRESULT hr;
hr = pr->QueryInterface(IID_IRowSchemaChange,(void **)&prsc);
if (SUCCEEDED(hr))
{
DBCOLUMNINFO dbColInfo[1] = {0};
DBCOLUMNACCESS *pdbColAcc = NULL;
DBID idCol;
idCol.eKind = DBKIND_NAME;
idCol.uName.pwszName = L"MyNewColumn";
dbColInfo[0].dwFlags = DBCOLUMNFLAGS_ISNULLABLE;
dbColInfo[0].ulColumnSize = 255;
dbColInfo[0].wType = DBTYPE_STR;
dbColInfo[0].columnid = idCol;
hr = prsc->AddColumns(1, dbColInfo, pdbColAcc);
}
return hr;
}
Figure 9 DBBINDURLFLAGs
Flag
|
Meaning
|
DBBINDURLFLAG_READ |
Open object for reading only. At least one of DBBINDURLFLAG_READ and DBBINDURLFLAG_WRITE must be set, either by setting the appropriate bits on dwBindURLFlags or by setting the corresponding bits of DBPROP_INIT_MODE. |
DBBINDURLFLAG_WRITE |
Open object for writing only. See DBBINDURLFLAG_READ. |
DBBINDURLFLAG_READWRITE |
Open object for reading and writing. See DBBINDURLFLAG_READ. |
DBBINDURLFLAG_SHARE_DENY_READ |
Deny others read access. Not all providers support all types of DENY semantics. If the provider does not support this type of DENY semantics, the bind will succeed but return DB_S_ERRORSOCCURRED and a status of DBBINDURLSTATUS_S_
DENYTYPENOTSUPPORTED. If the provider does not support any type of DENY semantics, the bind will succeed but return DB_S_ERRORSOCCURRED and a status of DBBINDURLSTATUS_S_DENYNOTSUPPORTED. |
DBBINDURLFLAG_SHARE_DENY_WRITE |
Deny others write access. See the notes for SHARE_DENY_READ for information about the behavior of providers that do not support this type of DENY semantics. |
DBBINDURLFLAG_SHARE_EXCLUSIVE |
Deny others read and write access. See the notes for SHARE_DENY_READ for information about the behavior of providers that do not support this type of DENY semantics. |
DBBINDURLFLAG_SHARE_DENY_NONE |
Do not deny others read or write access (equivalent to the omission of SHARE_DENY_READ and SHARE_DENY_WRITE). |
DBBINDURLFLAG_RECURSIVE |
Modifies DBBINDURLFLAG_SHARE_XXX. Propagate sharing restrictions to all objects in the subtree. Has no effect when binding to leaf nodes. Specifying this flag with only DBBINDURLFLAG_SHARE_DENY_NONE (or equivalently, with no SHARE_DENY flags) will result in E_INVALIDARG. |
DBBINDURLFLAG_OUTPUT |
Bind to the resource's executed output rather than its source. (For example, this will retrieve the HTML generated by an ASP file rather than its source.) This flag is ignored on binds to collections. |
DBBINDURLFLAG_ASYNCHRONOUS |
Return immediately and perform the binding on a separate thread. If DBBINDURLFLAG_WAITFORINIT is not specified, this flag affects the behavior of the IBindResource::Bind or ICreateRow::CreateRow call. If DBBINDURLFLAG_
WAITFORINIT is specified, this flag affects the behavior of the IDBInitialize::Initialize call. |
DBBINDURLFLAG_WAITFORINIT |
Return an interface supported on an uninitialized object, but do not initiate the bind. Used in the following cases: the object supports IDBInitialize and the caller must use IDBInitialize::Initialize to initiate the bind; or the caller intends to register callback interfaces by querying from the returned interface to IConnectionPointContainer. To poll for status or cancel an operation, the caller requests an IDBAsynchStatus interface. The consumer may only ask for interfaces supported on uninitialized objects. The provider returns E_NOINTERFACE if any other interface is requested. When IBindResource is implemented on an object other than a Binder (for example, when it is implemented on a Session or Row object as IScopedOperations, which is derived from IBindResource), this flag is disallowed because the data source object is already initialized. |
DBBINDURLFLAG_DELAYFETCHSTREAM |
On a bind to a row, this overrides the consumer's intent to immediately open the default stream. Absence of this flag is a hint to the provider to instantiate the default stream object and prefetch its contents. |
DBBINDURLFLAG_DELAYFETCHCOLUMNS |
On a bind to a row, this overrides the consumer's intent to immediately access the row's columns. Absence of this flag is a hint to the provider to download or prefetch the row's columns. |
Figure 10 CreateARow
HRESULT CreateARow(WCHAR *pwszName, bool bCollection)
{
HRESULT hr;
CComPtr<ICreateRow> pcr;
hr = CoCreateInstance(CLSID_ROOT_BINDER, NULL,
CLSCTX_INPROC_SERVER,
IID_ICreateRow, (void**)&pcr);
if (SUCCEEDED(hr))
{
DBBINDURLFLAG bf;
if (bCollection == true)
bf = DBBINDURLFLAG_COLLECTION |
DBBINDURLFLAG_READWRITE;
else
bf = DBBINDURLFLAG_READWRITE;
CComPtr<IRow> pr;
LPOLESTR *ppwszNewURL = NULL;
hr = pcr->CreateRow(NULL, pwszName, bf,
DBGUID_ROW,
IID_IRow, NULL, NULL, NULL,
ppwszNewURL, (IUnknown **)&pr);
}
return hr;
}
Figure 12 Resource Rowset Columns
Column Name
|
Column ID
|
Description
|
RESOURCE_PARSENAME
|
DBROWCOL_PARSENAME
|
Read-only URL of the resource. This name is usually a relative URL, although it can be an absolute URL. If the resource is the root of a tree, its parse name is defined to be an empty string.
|
RESOURCE_PARENTNAME
|
DBROWCOL_PARENTNAME
|
Read-only URL of the parent resource. The string always contains an absolute URL. If the resource is the root of tree, its parent name is defined to be an empty string.
|
RESOURCE_ABSOLUTEPARSENAME
|
DBROWCOL_ABSOLUTEPARSENAME
|
Read-only URL of the resource. This name is always an absolute URL, and for nonroot resources is the concatenation of its parent name and its parse name.
|
RESOURCE_ISHIDDEN
|
DBROWCOL_ISHIDDEN
|
VARIANT_TRUE means the resource is hidden. Therefore, no row will be returned in rowsets for it unless the command that created the rowset explicitly selected rows where RESOURCE_ISHIDDEN is VARIANT_TRUE.
|
RESOURCE_ISREAD ONLY
|
DBROWCOL_ISREADONLY
|
VARIANT_TRUE means the resource is read-only. Attempts to open this resource with DBBINDURLFLAG_WRITE return DB_E_READONLY. This property can be edited even when the resource has been opened only for reading.
|
RESOURCE_CONTENT TYPE
|
DBROWCOL_CONTENTTYPE
|
The MIME type of the document (for example, text/html).
|
RESOURCE_CONTENTCLASS
|
DBROWCOL_CONTENTCLASS
|
The likely use of the document. This might correspond to the Microsoft Office template used to create the document.
|
RESOURCE_CONTENTLANGUAGE
|
DBROWCOL_CONTENTLANGUAGE
|
The language in which the content is written (for example, U.S. English).
|
RESOURCE_CREATIONTIME
|
DBROWCOL_CREATIONTIME
|
Read-only, specifying a FILETIME structure containing the time the resource was created. The time is reported Coordinated Universal Time (UTC) format.
|
RESOURCE_LASTACCESSTIME
|
DBROWCOL_LASTACCESSTIME
|
Read-only, specifying a FILETIME structure containing the time that the resource was last accessed. The time is in UTC format. The FILETIME members are zero if provider does not support this time member.
|
RESOURCE_LASTWRITE TIME
|
DBROWCOL_LASTWRITETIME
|
Read-only time when the resource was last modified. The time is stored in a FILETIME structure in UTC format. If the provider does not support the time member, the remaining FILETIME members are set to zero.
|
RESOURCE_STREAMSIZE
|
DBROWCOL_STREAMSIZE
|
Read-only size of the resource’s default stream, in bytes.
|
RESOURCE_ISCOLLECTION
|
DBROWCOL_ISCOLLECTION
|
Read-only. VARIANT_TRUE means the resource is a collection. VARIANT_FALSE means the resource is atomic.
|
RESOURCE_ISSTRUCTURED DOCUMENT
|
DBROWCOL_ISSTRUCTURED DOCUMENT
|
VARIANT_TRUE means the resource is a structured document. VARIANT_FALSE means the resource is not a structured document. It could be a collection or an atomic resource.
|
DEFAULT_DOCUMENT
|
DBROWCOL_DEFAULT DOCUMENT
|
Read-only. This resource contains a URL to the default simple document of a folder or a structured document. This is used when the default IStream is requested from a resource. This property is blank for atomic resources.
|
CHAPTERED_CHILDREN
|
CHAPTERED_CHILDREN
|
Read-only, specifying the chapter of the rowset containing the children of the resource. (Optional)
|
RESOURCE_DISPLAYNAME
|
DBROWCOL_DISPLAYNAME
|
Read-only, displaying name of txhe resource.
|
RESOURCE_ISROOT
|
DBROWCOL_ISROOT
|
Read-only. VARIANT_TRUE means the resource is a root of a collection. Can be used with RESOURCE_ISCOLLECTION
|
Figure 13 dwMoveFlags Values
Flag Value |
Description
|
DBMOVE_ALLOW_EMULATION
|
If the attempt to move the row fails because the destination URL is on a different server or serviced by a different provider than the source, the provider is requested to attempt to simulate the move using download, upload, and delete operations. When moving resources between providers, this may cause increased latency or data loss due to different provider capabilities.
|
DBMOVE_ASYNC
|
The move operation is performed asynchronously. Progress and notifications are available via IDBAsynchStatus and IDBAsynchNotify callbacks. Implementations that do not support asynchronous behavior should block and return a warning.
|
DBMOVE_ATOMIC
|
Either all sources are moved successfully or no sources are moved. Whether all parts of an atomic operation are attempted if one part fails is provider-specific.
|
DBMOVE_DONT_UPDATE_LINKS
|
Request the server not to update links contained in an object on a move. If this flag is not specified, the default behavior is to do what the server specifies. By default, IScopedOperations::
Move will update links if the server is capable and if the option is turned on. If the server does not have the ability to fix up links or if the option is turned off, this call will still return S_OK.
|
DBMOVE_REPLACE_EXISTING
|
The move operation succeeds, even if a target object exists. Without this value, the move will fail if the target object already exists.
|
Figure 15 Record.Open Output
RESOURCE_PARSENAME = mypage.htm
RESOURCE_PARENTNAME = http://bob.com/
RESOURCE_ABSOLUTEPARSENAME = http://bob.com/sam.htm
RESOURCE_ISHIDDEN =
RESOURCE_ISREADONLY =
RESOURCE_CONTENTTYPE =
RESOURCE_CONTENTCLASS =
RESOURCE_CONTENTLANGUAGE =
RESOURCE_CREATIONTIME = 5/10/99 12:14:49 AM
RESOURCE_LASTACCESSTIME =
RESOURCE_LASTWRITETIME = 5/10/99 12:14:49 AM
RESOURCE_STREAMSIZE = 2
RESOURCE_ISCOLLECTION = False
RESOURCE_ISSTRUCTUREDDOCUMENT =
DEFAULT_DOCUMENT =
RESOURCE_DISPLAYNAME = mypage.htm
RESOURCE_ISROOT = False
RESOURCE_ISMARKEDFOROFFLINE = False
Figure 16 ADO Scoped Operations
Dim strURL As String
Dim rec As ADODB.Record
Dim rec2 As ADODB.Record
'StrURL points to a file
strURL = "http://bob.com/sam.htm"
'open a record representing the file
Set rec = New ADODB.Record
rec.Open strURL, , Access_DenyWrite
'copy it
rec.CopyRecord strURL, & _
"http://bob.com/ steve.htm"
'move it
rec.MoveRecord strURL & _
"http://bob.com/george.htm"
'delete it
Set rec2 = New ADODB.Record
rec2.Open "http://bob.com/george.htm"
rec2.DeleteRecord "http://bob.com/george.htm",
False