Interroger la base de données d'état

Cette rubrique contient des informations qui vous aideront à comprendre comment interroger la base de données d'état dans laquelle les données d'état actuelles du registre de chaîne de blocs sont stockées.

Qu'est-ce que la base de données d'État ?

Les données d'état actuelles du registre de chaîne de blocs sont stockées dans la base de données d'état.

Lorsque vous développez des codes chaîne Oracle Blockchain Platform, vous pouvez extraire des données de la base de données d'état en exécutant des requêtes enrichies. Oracle Blockchain Platform prend en charge les requêtes enrichies à l'aide de la syntaxe de requête enrichie SQL et des expressions de recherche CouchDB. Reportez-vous à Syntaxe de requête enrichie SQL et à CouchDBSyntaxe de requête enrichie.

Hyperledger Fabric ne prend pas en charge les requêtes enrichies SQL. Si votre réseau Oracle Blockchain Platform contient des participants Hyperledger Fabric, vous devez effectuer les opérations suivantes :

  • Si vos codes chaîne contiennent une syntaxe de requête SQL enrichie, ces codes chaîne sont installés uniquement sur les homologues membres à l'aide d'Oracle Blockchain Platform.

  • Si un code chaîne doit être installé sur des homologues Oracle Blockchain Platform et Hyperledger Fabric, utilisez la syntaxe CouchDB dans les codes chaîne et confirmez que les homologues Hyperledger Fabric sont configurés pour utiliser CouchDB en tant que référentiel de base de données d'état. Oracle Blockchain Platform peut traiter CouchDB.

Comment Oracle Blockchain Platform fonctionne-t-il avec Berkeley DB ?

Oracle Blockchain Platform utilise Oracle Berkeley DB comme base de données d'état. Oracle Blockchain Platform crée des tables relationnelles dans la base de données Berkeley en fonction de l'extension SQLite. Cette architecture offre un moyen robuste et performant de valider les requêtes SQL riches.

Pour chaque code chaîne de canal, Oracle Blockchain Platform crée une table de base de données Berkeley. Cette table stocke les données d'informations d'état et contient au moins une colonne de clé nommée key et une colonne de valeur nommée value ou valueJson, selon que vous utilisez des données au format JSON ou non.

Nom de la colonne Type Description
key TEXT Colonne de clé de la table d'état.
value TEXT Colonne de valeur de la table d'état.
valueJson TEXT Colonne de valeur de format JSON de la table d'état.

Les colonnes valueJson et value sont mutuellement exclusives. Par conséquent, si le code chaîne affecte une valeur JSON à une clé, la colonne valueJson contiendra cette valeur et la colonne de valeur sera définie sur NULL. Si le code chaîne affecte une valeur non JSON à une clé, la colonne valueJson est définie sur NULL et la colonne de valeur contient la valeur.

Exemple de base de données d'état

Voici des exemples de clés et leurs valeurs provenant de la base de données d'état de l'exemple Car Dealer :

clé value 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

Requêtes enrichies dans la console

Les administrateurs peuvent exécuter et analyser des requêtes enrichies à partir de la console.

  1. Accédez à la console et sélectionnez l'onglet Canaux.
  2. Dans la table des canaux, localisez le canal sur lequel exécuter une requête, cliquez sur le bouton Actions supplémentaires des canaux, puis sur Analyser les requêtes enrichies. La boîte de dialogue Analyser les requêtes enrichies est affichée.
  3. Pour exécuter une requête enrichie sur la base de données d'état, sélectionnez Exécution de requête.
    1. Dans Code chaîne, sélectionnez le code chaîne déployé sur le canal à interroger.
    2. Dans Pair, sélectionnez le pair à interroger.
      Seuls les homologues de l'organisation en cours qui exécutent le code chaîne sélectionné sont disponibles.
    3. Dans Requête enrichie, entrez la requête enrichie à exécuter et à analyser.
      Le format de requête doit respecter la syntaxe de requête enrichie. Pour plus d'informations sur la syntaxe de requête enrichie, reportez-vous à Syntaxe de requête enrichie prise en charge.
    4. Dans Limite de lignes de résultat, déplacez le curseur vers le nombre maximal de lignes de résultat à extraire. Vous pouvez extraire jusqu'à 50 lignes de résultats.
  4. Pour obtenir le plan d'exécution d'une requête, sélectionnez Explication du plan de requête. Un plan d'exécution de requête est la séquence d'opérations qui a été exécutée pour exécuter la requête.
    1. Dans Code chaîne, sélectionnez le code chaîne déployé sur le canal à interroger.
    2. Dans Pair, sélectionnez le pair à interroger.
    3. Dans Collecte, sélectionnez la base de données d'état ou la collecte de données privée.
    4. Dans Requête enrichie, entrez la requête enrichie.
      Le mot-clé explain n'est pas nécessaire pour cette requête.
      Par exemple : select * from <state>
  5. Cliquez sur Exécuter. Le champ Résultats affiche la table de résultats de la requête ou le plan d'exécution. Pour exporter la table de résultats en tant que fichier .csv, cliquez sur Exporter.
    La taille de la table de résultats est limitée à 1 Mo. Vous devrez peut-être affiner votre requête pour éviter de dépasser cette limite.

Syntaxe de requête enrichie prise en charge

Oracle Blockchain Platform prend en charge deux types de syntaxe de requête enrichie que vous pouvez utiliser pour interroger la base de données d'état : la requête enrichie SQL et la requête enrichie CouchDB.

Syntaxe de requête enrichie SQL

Les extensions JSON de Berkeley DB se présentent sous la forme de fonctions SQL.

Avant de commencer 

Notez les informations suivantes :

  • Vous pouvez uniquement accéder au code chaîne de canal (<STATE>) à partir duquel vous exécutez votre requête.
  • Seule l'instruction SELECT est prise en charge.
  • Vous ne pouvez pas modifier la table de base de données d'état.
  • Une expression de requête enrichie ne peut comporter qu'une seule instruction SELECT.
  • Les exemples de cette rubrique ne sont que quelques façons d'écrire votre requête enrichie. Vous avez accès à la syntaxe SQL complète habituelle pour interroger une base de données SQL.
  • Vous avez accès à l'extension JSON1 (extension SQLite). Reportez-vous à Extension JSON1 et à SQL tel que compris par SQLite.

Si vous avez besoin d'informations supplémentaires sur l'écriture et le test de codes chaîne, reportez-vous à Développement de codes chaîne.

Référence à la base de données d'état dans les requêtes

Le nom de la table de base de données d'état est géré en interne par Oracle Blockchain Platform. Vous n'avez donc pas besoin de connaître le nom physique de la base de données d'état lorsque vous écrivez un code chaîne.

A la place, vous devez utiliser l'alias <STATE> pour faire référence au nom de la table. Par exemple : select key, value from <STATE>.

L'alias <STATE> n'est pas sensible à la casse. Vous pouvez donc utiliser <state>, <STATE> ou un élément tel que <StAtE>.

Extraire toutes les clés

Utilisez la syntaxe suivante :

SELECT key FROM <STATE>

Par exemple, si vous utilisez cette syntaxe pour interroger l'exemple Car Dealer, vous obtiendrez la liste de clés suivante :

clé

abg1234

abg1235

ser1236

bra1238

dtrt10001

Extraire toutes les clés et valeurs triées par ordre alphabétique par clé

Utilisez la syntaxe suivante :

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

Par exemple, si vous utilisez cette syntaxe pour interroger l'exemple Car Dealer, vous obtiendrez les résultats suivants :

serialNumber détails
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}

Extraire toutes les clés et valeurs commençant par "abg"

Utilisez la syntaxe suivante :

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

Par exemple, si vous utilisez cette syntaxe pour interroger l'exemple Car Dealer, vous obtiendrez les résultats suivants :

serialNumber détails
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"}

Extraire toutes les clés avec des valeurs contenant une pièce de véhicule détenue par "Detroit Auto"

Utilisez la syntaxe suivante :

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

Par exemple, si vous utilisez cette syntaxe pour interroger l'exemple Car Dealer, vous obtiendrez la liste de clés suivante :

clé

abg1234

abg1235

ser1236

bra1238

Extraire le modèle et le fabricant de toutes les voitures appartenant à "Sam Dealer"

Utilisez la syntaxe suivante :

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'

Par exemple, si vous utilisez cette syntaxe pour interroger l'exemple Car Dealer, vous obtiendrez les résultats suivants :

modèle fabricant
un coupé Détroit Auto

Si la valeur d'état est un tableau JSON, vous pouvez utiliser cette syntaxe pour extraire le modèle et le fabricant de toutes les voitures appartenant à "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'

CouchDBSyntaxe de requête enrichie

Utilisez les informations de cette rubrique si vous migrez vos codes chaîne contenant la syntaxe CouchDB vers Oracle Blockchain Platform ou si vous devez écrire des codes chaîne à installer sur des homologues Hyperledger Fabric participant à un réseau Oracle Blockchain Platform.

Si vous écrivez un nouveau code chaîne, Oracle vous recommande d'utiliser des requêtes enrichies SQL pour tirer parti des avantages d'Oracle Blockchain Platform avec Berkeley DB en matière de performances.

Si vous avez besoin d'informations supplémentaires sur l'écriture et le test de codes chaîne, reportez-vous à Développement de codes chaîne.

Paramètres de requête et syntaxe de sélecteur non pris en charge

Oracle Blockchain Platform ne prend pas en charge le paramètre use_index. Si elle est utilisée, Oracle Blockchain Platform ignore ce paramètre et sélectionne automatiquement les index définis sur le fichier StateDB en question.

Paramètre Type Description
use_index JSON Demande à une requête d'utiliser un index spécifique.

Extraire tous les modèles, fabricants et propriétaires de voitures, et les commander par propriétaire

Utilisez cette expression :

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

Extraire le modèle et le fabricant pour toutes les voitures appartenant à "Sam Dealer"

Utilisez cette expression :

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

Index de base de données d'état

La base de données d'état peut contenir une grande quantité de données. Dans ce cas, Oracle Blockchain Platform utilise des index pour améliorer l'accès aux données.

Index par défaut

Lorsqu'un code chaîne est déployé, Oracle Blockchain Platform crée deux index.

  • Index de clé : créé sur la colonne de clé.

  • Index de valeur - Créé sur la colonne de valeur.

Index personnalisés

Dans certains cas, vous devrez peut-être créer des index personnalisés. Vous définissez ces index à l'aide de n'importe quelle expression pouvant être résolue dans le contexte de la table d'état. Les index personnalisés créés par rapport à la base de données Berkeley reposent sur la syntaxe SQLite, mais ils suivent sinon la même implémentation CouchDB fournie par Hyperledger Fabric.

Notez que vous pouvez utiliser des index personnalisés pour améliorer considérablement les performances des instructions WHERE et ORDER BY sur les jeux de données volumineux. Comme l'utilisation d'index personnalisés ralentit les insertions de données, vous devez les utiliser judicieusement.

Chaque index personnalisé est défini comme un tableau d'expressions, qui prend en charge les index composés, exprimés sous la forme d'un document JSON dans un fichier (notez qu'il y a un index par fichier). Vous devez packager ce fichier avec le code chaîne dans un dossier nommé "indexes" dans la structure de répertoires suivante : statedb/relationaldb/indexes. Reportez-vous à Ajout d'index CouchDB lors de l'installation du code chaîne.

Exemples d'index personnalisés

Les exemples d'index personnalisés de cette section utilisent l'exemple Concessionnaire automobile.

Exemple 1 : cet exemple indexe l'utilisation de l'expression json_extract dans le contexte des expressions WHERE et ORDER BY.

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

Exemple :

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

Exemple 2 - Cet exemple indexe l'utilisation composée des deux expressions json_extract dans le contexte des expressions WHERE et ORDER BY.

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

Exemple :

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

Exemple 3 - Cet exemple crée deux index : l'index décrit dans l'Exemple 1 et l'index décrit dans l'Exemple 2. Notez que chaque structure JSON doit être incluse dans un fichier distinct. Chaque fichier décrit un index unique : un index simple comme l'exemple 1 ou un index composé comme l'exemple 2.

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

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

Dans l'exemple suivant, l'index 2 est appliqué à l'expression AND dans la partie WHERE de la requête, tandis que l'index 1 est appliqué à l'expression ORDER BY :

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

Format de document JSON

Le document JSON doit avoir le format suivant :

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

Exemple :

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

Différences dans la validation des requêtes enrichies

Dans certains cas, Hyperledger Fabric standard avec requête enrichie CouchDB et la requête enrichie Oracle Berkeley DB se comportent différemment.

Dans Hyperledger Fabric standard avec CouchDB, chaque paire clé/valeur renvoyée par la requête est ajoutée au jeu de lecture de la transaction et validée au moment de la validation et sans réexécution de la requête. Dans Berkeley DB, la paire clé/valeur renvoyée n'est pas ajoutée au jeu de lecture, mais le résultat de la requête enrichie est haché dans un arbre Merkle et validé par rapport à la réexécution de la requête au moment de la validation.

Hyperledger Fabric natif ne fournit pas de protection des données pour les requêtes enrichies. Toutefois, Berkeley DB contient une fonctionnalité qui protège et valide la requête enrichie en ajoutant la valeur de hachage de l'arbre Merkle dans l'ensemble de lecture, en réexécutant la requête enrichie et en recalculant la valeur de l'arbre Merkle à l'étape de validation. Etant donné que la validation est plus précise dans Oracle Blockchain Platform avec Berkeley DB, les appels de code chaîne sont parfois signalés pour des lectures fantômes plus fréquentes.