Suporte a conjuntos de linhas do esquema
Conjuntos de linhas do esquema permitem que os consumidores obter informações sobre o armazenamento de dados sem saber sua estrutura subjacente ou esquema.Por exemplo, um armazenamento de dados pode ter tabelas organizadas em uma hierarquia definida pelo usuário, portanto, não haveria nenhuma maneira de garantir o conhecimento do esquema, exceto por leitura.(Como outro exemplo, observe que os assistentes do Visual C++ usam conjuntos de linhas do esquema para gerar acessadores para o consumidor). Para permitir que o consumidor fazer isso, o objeto de sessão do provedor expõe métodos sobre o IDBSchemaRowset interface.Em aplicativos do Visual C++, use o IDBSchemaRowsetImpl classe para implementar IDBSchemaRowset.
IDBSchemaRowsetImplsuporta os seguintes métodos:
CheckRestrictions verifica a validade das restrições contra um conjunto de linhas do esquema.
CreateSchemaRowset implementa uma função de criador de objeto COM para o objeto especificado pelo parâmetro de modelo.
SetRestrictions Especifica quais restrições você dá suporte em um conjunto de linhas de esquema específico.
IDBSchemaRowset::GetRowset retorna um conjunto de linhas do esquema (herdado da interface).
GetSchemas retorna uma lista de conjuntos de linhas do esquema acessível por IDBSchemaRowsetImpl::GetRowset (herdado da interface).
Suporte a ATL OLE DB Provider Assistente
ATL OLE DB Provider Wizard cria três classes de esquema no arquivo de cabeçalho de sessão:
CShortNameSessionTRSchemaRowset
CShortNameSessionColSchemaRowset
CShortNameSessionPTSchemaRowset
Essas classes respondem às solicitações de consumidor de informações do esquema; Observe que a especificação OLE DB requer suporte esses conjuntos de linhas do esquema de três:
CShortNameSessionTRSchemaRowset manipula solicitações de informações da tabela (o DBSCHEMA_TABLES o conjunto de linhas do esquema).
CShortNameSessionColSchemaRowset manipula solicitações de informações de coluna (o DBSCHEMA_COLUMNS o conjunto de linhas do esquema).O assistente fornece exemplos de implementações para essas classes, que retornam informações de esquema para um provedor DOS.
CShortNameSessionPTSchemaRowset manipula solicitações de informações de esquema sobre o tipo de provedor (o DBSCHEMA_PROVIDER_TYPES o conjunto de linhas do esquema).Retorna a implementação padrão fornecida pelo Assistente de S_OK.
Você pode personalizar essas classes para tratar informações de esquema apropriadas para seu provedor:
Em cShortNameSessionTRSchemaRowset, você deve preencher os campos de descrição de catálogo e tabela (trData.m_szType, trData.m_szTable, e trData.m_szDesc).O exemplo gerado pelo assistente usa apenas uma linha (tabela).Outros provedores podem retornar mais de uma tabela.
Em cShortNameSessionColSchemaRowset, passe o nome da tabela como um DBID.
Definição de restrições
Um conceito importante no suporte ao conjunto de linhas do esquema é definir restrições usando SetRestrictions.Restrições permitem que os consumidores buscar somente as linhas correspondentes (por exemplo, encontrar todas as colunas na tabela "MyTable").As restrições são opcionais e no caso em que nenhum são suportadas (o padrão), todos os dados é sempre retornado.Para obter um exemplo de um provedor que oferece suporte a restrições, consulte o UpdatePV exemplo.
Configurando o mapa de esquema
Configure um mapa de esquema como no Session.h em UpdatePV:
BEGIN_SCHEMA_MAP(CUpdateSession)
SCHEMA_ENTRY(DBSCHEMA_TABLES, CUpdateSessionTRSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_COLUMNS, CUpdateSessionColSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_PROVIDER_TYPES, CUpdateSessionPTSchemaRowset)
END_SCHEMA_MAP()
Suporte IDBSchemaRowset, você deve oferecer suporte a DBSCHEMA_TABLES, DBSCHEMA_COLUMNS, e DBSCHEMA_PROVIDER_TYPES.Você pode adicionar conjuntos de linhas do esquema adicionais a seu critério.
Declare uma classe de conjunto de linhas do esquema com um Execute método como CUpdateSessionTRSchemaRowset em UpdatePV:
class CUpdateSessionTRSchemaRowset :
public CSchemaRowsetImpl < CUpdateSessionTRSchemaRowset,
CTABLESRow, CUpdateSession >
...
// Execute looks like this; what pointers does the consumer use?
HRESULT Execute(DBROWCOUNT* pcRowsAffected,
ULONG cRestrictions, const VARIANT* rgRestrictions)
Observe que CUpdateSession herda de IDBSchemaRowsetImpl, portanto, ele tem todas as restrições métodos de manipulação.Usando CSchemaRowsetImpl, declarar três classes filhas (listados no mapa de esquema acima): CUpdateSessionTRSchemaRowset, CUpdateSessionColSchemaRowset, e CUpdateSessionPTSchemaRowset.Cada uma dessas classes filho tem uma Execute método que manipula o seu respectivo conjunto de restrições (critérios de pesquisa).Cada Execute método compara os valores de cRestrictions e rgRestrictions parâmetros.Consulte a descrição desses parâmetros no SetRestrictions.
Para obter mais informações sobre quais restrições correspondem a um conjunto de linhas de esquema específico, consulte a tabela de conjunto de linhas do esquema GUIDs em IDBSchemaRowset na referência OLE DB Programmer na Windows SDK.
Por exemplo, se você oferece suporte a TABLE_NAME restrição DBSCHEMA_TABLES, faça o seguinte:
Primeiro, procure DBSCHEMA_TABLES e ver o que ele oferece suporte a quatro restrições (em ordem).
Restrição de conjunto de linhas do esquema |
Valor de restrição |
---|---|
TABLE_CATALOG |
0x1 (1 binário) |
TABLE_SCHEMA |
0x2 (10 binário) |
TABLE_NAME |
0x4 (100 binário) |
TABLE_TYPE |
0x8 (1000 binário) |
Em seguida, observe que existe um bit para cada restrição.Porque você deseja oferecer suporte a TABLE_NAME somente retornaria 0x4 na rgRestrictions elemento.Se você suporte TABLE_CATALOG e TABLE_NAME, retornaria 0x5 (101 binário).
Por padrão, a implementação retorna 0 (não oferece suporte a quaisquer restrições) para qualquer solicitação.UpdatePV é um exemplo de um provedor que oferece suporte a restrições.
Exemplo
Esse código é retirado da UpdatePV exemplo.UpdatePv suporta os três conjuntos de linhas de esquema necessária: DBSCHEMA_TABLES, DBSCHEMA_COLUMNS, e DBSCHEMA_PROVIDER_TYPES.Como um exemplo de como implementar o suporte ao esquema no seu provedor, este tópico leva você através de implementação de DBSCHEMA_TABLE o conjunto de linhas.
Observação |
---|
O exemplo de código pode diferir do que está listado aqui; Você deve considerar o código de exemplo como a versão mais atualizada. |
Adicionando suporte a esquema a primeira etapa é determinar quais restrições que você pretende oferecer suporte.Para determinar quais restrições estão disponíveis para o conjunto de linhas do esquema, examine a especificação OLE DB para a definição de IDBSchemaRowset.Após a definição do principal, você verá uma tabela que contém o nome de conjunto de linhas do esquema, o número de restrições e as colunas de restrição.Selecione o conjunto de linhas de esquema que você deseja oferecer suporte e anote o número de colunas de restrição e restrições.Por exemplo, DBSCHEMA_TABLES aceita quatro restrições (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, e TABLE_TYPE):
void SetRestrictions(ULONG cRestrictions, GUID* rguidSchema,
ULONG* rgRestrictions)
{
for (ULONG l=0; l<cRestrictions; l++)
{
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
else if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_COLUMNS))
rgRestrictions[l] = 0x04;
else if (InlineIsEqualGUID(rguidSchema[l],
DBSCHEMA_PROVIDER_TYPES))
rgRestrictions[l] = 0x00;
}
}
Um bit representa cada coluna de restrição.Se você quiser suportar uma restrição (ou seja, você pode consultar por ele), defina esse bit para 1.Se não desejar oferecer suporte a uma restrição, defina esse bit para zero.A partir da linha de código acima, UpdatePV oferece suporte a TABLE_NAME e TABLE_TYPE restrições sobre o DBSCHEMA_TABLES rowset.Esses são o terceiro (máscara de bits 100) e o quarta restrições (máscara de bits 1000).Portanto, a máscara de bits de UpdatePv é 1100 (ou 0x0C):
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
O seguinte Execute função é semelhante aos conjuntos de linhas regulares.Você tem três argumentos: pcRowsAffected, cRestrictions, e rgRestrictions.O pcRowsAffected variável é um parâmetro de saída que o provedor pode retornar a contagem de linhas no conjunto de linhas do esquema.O cRestrictions parâmetro é um parâmetro de entrada que contém o número de restrições que passaram pelo consumidor para o provedor.O rgRestrictions parâmetro é uma matriz de VARIANT valores que contêm os valores de restrição.
HRESULT Execute(DBROWCOUNT* pcRowsAffected, ULONG cRestrictions,
const VARIANT* rgRestrictions)
O cRestrictions variável é baseado no número total de restrições para um conjunto de linhas do esquema, independentemente se o provedor de suporte.Como UpdatePv oferece suporte a duas restrições (a terceira e quarta), esse código somente procura por um cRestrictions valor maior ou igual a três.
O valor para o TABLE_NAME restrição é armazenada em rgRestrictions[2] (novamente, a terceira restrição em uma matriz baseada em zero é 2).Você precisa verificar se a restrição não é VT_EMPTY suporte realmente.Observe que VT_NULL não é igual a VT_EMPTY.VT_NULL Especifica um valor de restrição válida.
A definição de UpdatePv de um nome de tabela é um nome de caminho totalmente qualificado para um arquivo de texto.Extrair o valor de restrição e tentar abrir o arquivo para garantir que o arquivo existe realmente.Se o arquivo não existir, retornar S_OK.Isso pode parecer um pouco para trás, mas o código que realmente está informando o consumidor é que não havia nenhum tabelas com suporte pelo nome especificado.O S_OK retorno significa que o código seja executado corretamente.
USES_CONVERSION;
enum {
sizeOfszFile = 255
};
CTABLESRow trData;
FILE *pFile = NULL;
TCHAR szFile[ sizeOfszFile ];
errcode err = 0;
// Handle any restrictions sent to us. This only handles
// the TABLE_NAME & TABLE_TYPE restictions (the 3rd and 4th
// restrictions in DBSCHEMA_TABLES...look in IDBSchemaRowsets
// in part 2 of the prog. ref) so your restrictions are 0x08 & 0x04
// for a total of (0x0C)
if (cRestrictions >= 3 && rgRestrictions[2].vt != VT_EMPTY)
{
CComBSTR bstrName = rgRestrictions[2].bstrVal;
if ((rgRestrictions[2].vt == VT_BSTR) && (bstrName != (BSTR)NULL))
{
// Check to see if the file exists
_tcscpy_s(&szFile[0], sizeOfszFile, OLE2T(bstrName));
if (szFile[0] == _T('\0') ||
((err = _tfopen(&pFile, &szFile[0], _T("r"))) == 0))
{
return S_OK;// Their restriction was invalid return no data
}
else
{
fclose(pFile);
}
}
}
Suporte a quarta restrição (TABLE_TYPE) é semelhante à terceira restrição.Verifique o valor não é VT_EMPTY.Essa restrição só retorna o tipo de tabela, tabela.Para determinar os valores válidos para o DBSCHEMA_TABLES, procure no Apêndice B do referência OLE DB Programmer na tabelas seção de conjunto de linhas.
// TABLE_TYPE restriction:
if (cRestrictions >=4 && rgRestrictions[3].vt != VT_EMPTY)
{
CComBSTR bstrType = rgRestrictions[3].bstrVal;
if ((rgRestrictions[3].vt == VT_BSTR) && (bstrType != (BSTR)NULL))
{
// This is kind of a blind restriction.
// This only actually supports
// TABLES so if you get anything else,
// just return an empty rowset.
if (_tcscmp(_T("TABLE"), OLE2T(bstrType)) != 0)
return S_OK;
}
}
Isso é onde você realmente criar uma entrada de linha para o conjunto de linhas.A variável trData corresponde a CTABLESRow, uma estrutura definida nos modelos de provedor OLE DB.CTABLESRow corresponde do tabelas definição de conjunto de linhas no Apêndice B da especificação do OLE DB.Você só tem uma linha para adicionar pois suporta apenas uma tabela por vez.
// Bring over the data:
wcspy_s(trData.m_szType, OLESTR("TABLE"), 5);
wcspy_s(trData.m_szDesc, OLESTR("The Directory Table"), 19);
wcsncpy_s(trData.m_szTable, T2OLE(szFile), _TRUNCATE());
UpdatePV define somente três colunas: TABLE_NAME, TABLE_TYPE, e Descrição.Você deve fazer uma nota das colunas para o qual retornar informações, porque essas informações são necessárias quando você implementar GetDBStatus:
_ATLTRY
{
m_rgRowData.Add(trData);
}
_ATLCATCHALL()
{
return E_OUTOFMEMORY;
}
//if (!m_rgRowData.Add(trData))
// return E_OUTOFMEMORY;
*pcRowsAffected = 1;
return S_OK;
}
O GetDBStatus função é muito importante para a operação correta do conjunto de linhas do esquema.Porque você não retorne dados para cada coluna de tabelas conjunto de linhas, você precisará especificar quais colunas você retorna dados para e que não.
virtual DBSTATUS GetDBStatus(CSimpleRow* , ATLCOLUMNINFO* pColInfo)
{
ATLASSERT(pColInfo != NULL);
switch(pColInfo->iOrdinal)
{
case 3: // TABLE_NAME
case 4: // TABLE_TYPE
case 6: // DESCRIPTION
return DBSTATUS_S_OK;
break;
default:
return DBSTATUS_S_ISNULL;
break;
}
}
Porque seu Execute função retorna dados para o TABLE_NAME, TABLE_TYPE, e Descrição os campos de tabelas conjunto de linhas, você pode procurar no Apêndice B da especificação OLE DB e determinar (contando de cima para baixo) que são ordinais 3, 4 e 6.Para cada uma dessas colunas, retornar DBSTATUS_S_OK.Para todas as outras colunas, retornar DBSTATUS_S_ISNULL.É importante retornar esse status porque um consumidor pode não entender que é o valor que você retornar Nulo ou algo mais.Novamente, observe que Nulo não é equivalente ao vazio.
Para obter mais informações sobre a interface de conjunto de linhas do esquema OLE DB, consulte o IDBSchemaRowset interface na referência o OLE DB Programmer.
Para obter informações sobre como usar os consumidores IDBSchemaRowset métodos, consulte Obtenção de metadados com conjuntos de linhas do esquema.
Um exemplo de um provedor que ofereça suporte a conjuntos de linhas do esquema, consulte o UpdatePV exemplo.