Consultar o Banco de Dados de Estado

Este tópico contém informações para ajudá-lo a entender como consultar o banco de dados de estado em que os dados de estado atuais do razão blockchain são armazenados.

O que é o Banco de Dados de Estado?

Os dados de estado atuais do razão blockchain são armazenados no banco de dados de estado.

Ao desenvolver códigos de cadeia do Oracle Blockchain Platform, você pode extrair dados do banco de dados de estado executando consultas avançadas. O Oracle Blockchain Platform suporta consultas avançadas usando a sintaxe de consulta avançada SQL e as expressões de localização CouchDB. Consulte Sintaxe de Consulta Avançada SQL e Sintaxe de Consulta Avançada CouchDB.

O Hyperledger Fabric não suporta consultas ricas em SQL. Se sua rede do Oracle Blockchain Platform contiver participantes do Hyperledger Fabric, certifique-se de fazer o seguinte:

  • Se seus chaincodes contiverem sintaxe de consulta rica em SQL, esses chaincodes serão instalados apenas nos pares de membros usando o Oracle Blockchain Platform.

  • Se um chaincode precisar ser instalado nos pares Oracle Blockchain Platform e Hyperledger Fabric, use a sintaxe CouchDB nos chaincodes e confirme se os pares Hyperledger Fabric estão configurados para usar CouchDB como seu repositório de banco de dados de estado. O Oracle Blockchain Platform pode processar CouchDB.

Como o Oracle Blockchain Platform Funciona com o Berkeley DB?

O Oracle Blockchain Platform usa o Oracle Berkeley DB como banco de dados de estado. O Oracle Blockchain Platform cria tabelas relacionais no BD Berkeley com base na extensão SQLite. Essa arquitetura fornece uma maneira robusta e eficiente de validar consultas ricas em SQL.

Para cada chaincode de canal, o Oracle Blockchain Platform cria uma tabela de banco de dados Berkeley. Essa tabela armazena dados de informações de estado e contém pelo menos uma coluna de chave chamada key e uma coluna de valor chamada value ou valueJson, dependendo se você está usando dados de formato JSON.

Nome da Coluna Tipo Descrição
key TEXT Coluna-chave da tabela de estado.
value TEXT Coluna de valor da tabela de estado.
valueJson TEXT Coluna de valor do formato JSON da tabela de estado.

Observe que as colunas valueJson e value são mutuamente exclusivas. Portanto, se o chaincode designar um valor JSON a uma chave, a coluna valueJson conterá esse valor, e a coluna de valor será definida como nula. Se o chaincode designar um valor não JSON a uma chave, a coluna valueJson será definida como nula e a coluna de valor conterá o valor.

Exemplo de um Banco de Dados de Estado

Estes são exemplos de chaves e seus valores do banco de dados de estado da amostra da Concessionária de Veículos:

chave valor valueJson
abg1234 null {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
abg1235 null {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
ser1236 null {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
bra1238 null {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "name": "brakepad 4200", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
dtrt10001 null {"docType": "vehicle", "chassisNumber": "dtrt10001", "manufacturer": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979

Consultas Avançadas na Console

Os administradores podem executar e analisar consultas avançadas no console.

  1. Vá para a console e selecione a guia Canais.
  2. Na tabela de canais, localize o canal no qual você deseja executar uma consulta, clique no botão Mais Ações dos canais e, em seguida, clique em Analisar Consultas Avançadas. A caixa de diálogo Analisar Consultas Avançadas é exibida.
  3. Para executar uma consulta avançada no banco de dados de estado, selecione Execução de Consulta.
    1. Para Código de Cadeia, selecione o código de cadeia implantado no canal que você deseja consultar.
    2. Para Par, selecione o par a ser consultado.
      Apenas pares na organização atual que estão executando o chaincode selecionado estão disponíveis.
    3. Para Consulta Rica, informe a consulta avançada a ser executada e analisada.
      O formato de consulta deve seguir a sintaxe rich query. Para obter mais informações sobre a sintaxe de rich query, consulte Sintaxe de Rich Query Suportada.
    4. Para Limite de Linhas de Resultado, mova o controle deslizante para o número máximo de linhas de resultado a serem extraídas. Você pode extrair até 50 linhas de resultados.
  4. Para obter o plano de execução de uma consulta, selecione Explicação do Plano de Consulta. Um plano de execução de consulta é a sequência de operações que foram executadas para executar a consulta.
    1. Para Código de Cadeia, selecione o código de cadeia implantado no canal que você deseja consultar.
    2. Para Par, selecione o par a ser consultado.
    3. Para Coleção, selecione o banco de dados de estado ou a coleta de dados privada.
    4. Para Consulta Avançada, informe a consulta avançada.
      A palavra-chave explain não é necessária para esta consulta.
      Por exemplo: select * from <state>
  5. Clique em Executar. O campo Resultados mostra a tabela de resultados da consulta ou o plano de execução. Para exportar a tabela de resultados como um arquivo .csv, clique em Exportar.
    O tamanho da tabela de resultados é limitado a 1 MB. Talvez seja necessário refinar sua consulta para evitar exceder esse limite.

Sintaxe de Rich Query Suportada

O Oracle Blockchain Platform suporta dois tipos de sintaxe de consulta avançada que você pode usar para consultar o banco de dados de estado: consulta rica em SQL e consulta rica em CouchDB.

Sintaxe da Consulta Avançada SQL

As extensões Berkeley DB JSON são na forma de funções SQL.

Antes de Começar

Observe as seguintes informações:

  • Você só pode acessar o chaincode do canal (<STATE>) do qual está executando sua consulta.
  • Só há suporte para a instrução SELECT.
  • Não é possível modificar a tabela do banco de dados de estado.
  • Uma expressão de consulta rica pode ter apenas uma instrução SELECT.
  • Os exemplos neste tópico são apenas algumas maneiras de escrever sua consulta avançada. Você tem acesso à sintaxe SQL completa usual para consultar um banco de dados SQL.
  • Você tem acesso à Extensão JSON1 (extensão SQLite). Consulte JSON1 Extension e SQL As Understood by SQLite.

Se precisar de mais informações sobre como gravar e testar chaincodes, consulte Desenvolver Chaincodes.

Como Consultar o Banco de Dados de Estado em Consultas

O nome da tabela do banco de dados de estado é gerenciado internamente pelo Oracle Blockchain Platform, portanto, você não precisa saber o nome físico do banco de dados de estado ao gravar um chaincode.

Em vez disso, use o alias <STATE> para fazer referência ao nome da tabela. Por exemplo: select key, value from <STATE>.

Observe que o alias <STATE> não faz distinção entre maiúsculas e minúsculas; portanto, você pode usar <state>, <STATE> ou algo como <StAtE>.

Recuperar Todas as Chaves

Use esta sintaxe:

SELECT key FROM <STATE>

Por exemplo, se você usar essa sintaxe para consultar a amostra Concessionária de Veículos, obterá a seguinte lista de chaves:

chave

abg1234

abg1235

ser1236

bra1238

dtrt10001

Recuperar Todas as Chaves e Valores Ordenados Alfabeticamente por Chave

Use esta sintaxe:

SELECT key AS serialNumber, valueJson AS details FROM  <state> ORDER BY key

Por exemplo, se você usar essa sintaxe para consultar a amostra Concessionária de Veículos, obterá os seguintes resultados:

serialNumber detalhes
abg1234 {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
abg1235 {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
bra1238 {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "name": "brakepad 4200", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
dtrt10001 {"docType": "vehicle", "chassisNumber": "dtrt10001", "manufacturer": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979
ser1236 {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}

Recuperar Todas as Chaves e Valores Começando com "abg"

Use esta sintaxe:

SELECT key AS serialNumber, valueJson AS details FROM <state> WHERE key LIKE 'abg%'SELECT key, value FROM <STATE>

Por exemplo, se você usar essa sintaxe para consultar a amostra Concessionária de Veículos, obterá os seguintes resultados:

serialNumber detalhes
abg1234 {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": "1502688979", "name": "airbag 2020", "owner": "Detroit Auto", "recall": "false", "recallDate": "1502688979"}
abg1235 {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": "1502688979", "name": "airbag 4050", "owner": "Detroit Auto", "recall": "false", "recallDate": "1502688979"}

Recuperar Todas as Chaves com Valores que Contêm uma Peça de Veículo de Propriedade de "Detroit Auto"

Use esta sintaxe:

SELECT key FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'

Por exemplo, se você usar essa sintaxe para consultar a amostra Concessionária de Veículos, obterá a seguinte lista de chaves:

chave

abg1234

abg1235

ser1236

bra1238

Recuperar Modelo e Fabricante de todos os Carros de Propriedade da "Concessionária Sam"

Use esta sintaxe:

SELECT json_extract(valueJson, '$.model') AS model, json_extract(valueJson, '$.manufacturer') AS manufacturer FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehicle' AND json_extract(valueJson, '$.owner') = 'Sam Dealer'

Por exemplo, se você usar essa sintaxe para consultar a amostra Concessionária de Veículos, obterá os seguintes resultados:

modelo fabricante
um cupê Detroit Auto

Se o valor do estado for array JSON, você poderá usar essa sintaxe para recuperar o modelo e o fabricante de todos os carros de propriedade de "Sam Dealer":

SELECT json_extract(j.value, '$.model') AS model, json_extract(j.value, '$.manufacturer') AS manufacturer FROM <state> s, json_each(json_extract(s.valueJson,'$')) j WHERE json_valid(j.value) AND json_extract(j.value, '$.owner') = 'Sam Dealer'

CouchDB Sintaxe de Rich Query

Use as informações deste tópico se você estiver migrando seus chaincodes contendo a sintaxe CouchDB para o Oracle Blockchain Platform ou se precisar gravar chaincodes para instalar em pares do Hyperledger Fabric que participam de uma rede do Oracle Blockchain Platform.

Se você estiver escrevendo um novo chaincode, a Oracle recomenda que você use consultas ricas em SQL para aproveitar os benefícios de desempenho que o Oracle Blockchain Platform com o Berkeley DB fornece.

Se precisar de mais informações sobre como gravar e testar chaincodes, consulte Desenvolver Chaincodes.

Parâmetros de Consulta e Sintaxe do Seletor Não Suportados

O Oracle Blockchain Platform não suporta o parâmetro use_index. Se usado, o Oracle Blockchain Platform ignorará esse parâmetro e escolherá automaticamente os índices definidos no StateDB em questão.

Parâmetro Tipo Descrição
use_index json Instrui uma consulta a usar um índice específico.

Recuperar Todos os Modelos, Fabricantes e Proprietários de Carros e Ordená-los por Proprietário

Use esta expressão:

{ 
  "fields": ["model", "manufacturer", "owner"], 
  "sort": [   
    "owner" 
   ]
}

Recuperar Modelo e Fabricante para Todos os Carros de Propriedade da "Concessionária Sam"

Use esta expressão:

{ 
  "fields": ["model", "manufacturer"], 
  "selector": {   
    "docType"  : "vehicle",
     "owner" : "Sam Dealer" 
  }
}

Índices do Banco de Dados de Estado

O banco de dados de estado pode conter uma grande quantidade de dados. Nesses casos, o Oracle Blockchain Platform usa índices para melhorar o acesso aos dados.

Índices Padrão

Quando um chaincode é implantado, o Oracle Blockchain Platform cria dois índices.

  • Índice de chave - Criado na coluna de chave.

  • Índice de valor - Criado na coluna de valor.

Índices Personalizados

Em alguns casos, talvez você precise criar índices personalizados. Você define esses índices usando qualquer expressão que possa ser resolvida no contexto da tabela de estado. Os índices personalizados criados com o Berkeley DB dependem da sintaxe SQLite, mas seguem a mesma implementação CouchDB fornecida pelo Hyperledger Fabric.

Observe que você pode usar índices personalizados para melhorar drasticamente o desempenho das instruções WHERE e ORDER BY em grandes conjuntos de dados. Como o uso de índices personalizados retarda as inserções de dados, você deve usá-los com critério.

Cada índice personalizado é definido como uma matriz de expressões, que suportam índices compostos, expressos como um documento JSON dentro de um arquivo (observe que há um índice por arquivo). Você deve empacotar esse arquivo com o chaincode em uma pasta chamada "indexes" na seguinte estrutura de diretórios: statedb/relationaldb/indexes. Consulte Como adicionar índices CouchDB durante a instalação do chaincode.

Exemplo de Índices Personalizados

Os exemplos de índice personalizados nesta seção usam a amostra Concessionária de automóveis.

Exemplo 1 - Este exemplo indexa o uso da expressão json_extract no contexto das expressões WHERE e ORDER BY.

{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

Por exemplo:

SELECT … FROM … ORDER BY json_extract(valueJson, '$.owner')

Exemplo 2 - Este exemplo indexa o uso composto das duas expressões json_extract no contexto das expressões WHERE e ORDER BY.

{"indexExpressions": ["json_extract(valueJson, '$.docType')", "json_extract(valueJson, '$.owner')"]}

Por exemplo:

SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'

Exemplo 3 - Este exemplo cria dois índices: o índice descrito no Exemplo 1 e o índice descrito no Exemplo 2. Observe que cada estrutura JSON precisa ser incluída em um arquivo separado. Cada arquivo descreve um único índice: um índice simples como o Exemplo 1 ou um índice composto como o Exemplo 2.

Índice 1: {"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

Índice 2: {"indexExpressions": ["json_extract(valueJson, '$owner')", "json_extract(valueJson, '$.docType')"]}

No exemplo a seguir, o Índice 2 é aplicado à expressão AND na parte WHERE da consulta, enquanto o Índice 1 é aplicado à expressão ORDER BY:

SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto' ORDER BY json_extract(valueJson, '$.owner')

Formato de Documento JSON

O documento JSON deve estar no seguinte formato:

{"indexExpressions": [expr1, ..., exprN]}

Por exemplo:

{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

Diferenças na Validação de Consultas Avançadas

Em alguns casos, o Hyperledger Fabric padrão com consulta avançada CouchDB e a consulta avançada do Oracle Berkeley DB se comportam de maneira diferente.

No Hyperledger Fabric padrão com CouchDB, cada par de chave e valor retornado pela consulta é adicionado ao conjunto de leitura da transação e é validado no momento da validação e sem reexecutar a consulta. No Berkeley DB, o par de chave e valor retornado não é adicionado ao conjunto de leitura, mas o resultado da consulta rica é hashado em uma árvore Merkle e validado em relação à reexecução da consulta no momento da validação.

O Hyperledger Fabric nativo não fornece proteção de dados para consultas avançadas. No entanto, o Berkeley DB contém uma funcionalidade que protege e valida a consulta avançada adicionando o valor de hash da árvore Merkle ao conjunto de leitura, reexecutando a consulta avançada e, no estágio de validação, recalculando o valor da árvore Merkle. Observe que, como a validação é mais precisa no Oracle Blockchain Platform com o Berkeley DB, as chamadas de chaincode às vezes são sinalizadas para leituras fantasmas mais frequentes.