Esegui query sul database di stato

Questo argomento contiene informazioni per aiutarti a capire come eseguire query sul database di stato in cui sono memorizzati i dati di stato correnti del libro contabile blockchain.

Cos'è il database di stato?

I dati di stato correnti del libro mastro blockchain sono memorizzati nel database di stato.

Quando sviluppi i codici concatenati di Oracle Blockchain Platform, puoi estrarre i dati dal database di stato eseguendo query complesse. Oracle Blockchain Platform supporta query avanzate utilizzando la sintassi SQL Rich Query e le espressioni di ricerca CouchDB. Vedere Sintassi SQL Rich Query e CouchDB Rich Query Syntax.

Hyperledger Fabric non supporta le query SQL Rich. Se la rete Oracle Blockchain Platform contiene partecipanti a Hyperledger Fabric, è necessario eseguire le operazioni riportate di seguito.

  • Se i codici concatenati contengono una sintassi di query avanzata SQL, tali codici concatenati vengono installati solo sui peer membri che utilizzano Oracle Blockchain Platform.

  • Se è necessario installare un codice concatenato nei peer di Oracle Blockchain Platform e Hyperledger Fabric, utilizzare la sintassi CouchDB nei codici concatenati e confermare che i peer di Hyperledger Fabric sono impostati per utilizzare CouchDB come repository del database di stato. Oracle Blockchain Platform può elaborare CouchDB.

Come funziona Oracle Blockchain Platform con Berkeley DB?

Oracle Blockchain Platform utilizza Oracle Berkeley DB come database di stato. Oracle Blockchain Platform crea tabelle relazionali nel database Berkeley in base all'estensione SQLite. Questa architettura offre un modo efficace e performante per convalidare query avanzate SQL.

Per ogni codice concatenato di canale, Oracle Blockchain Platform crea una tabella DB Berkeley. Questa tabella memorizza i dati delle informazioni sullo stato e contiene almeno una colonna chiave denominata key e una colonna di valori denominata value o valueJson, a seconda che si stiano utilizzando i dati del formato JSON.

Nome della colonna Type Descrizione
key TEXT Colonna chiave della tabella dello stato.
value TEXT Colonna valore della tabella stato.
valueJson TEXT Colonna dei valori del formato JSON della tabella di stato.

Si noti che le colonne valueJson e value si escludono a vicenda. Pertanto, se il codice concatenato assegna un valore JSON a una chiave, la colonna valueJson conterrà tale valore e la colonna del valore verrà impostata su null. Se il codice concatenato assegna un valore non JSON a una chiave, la colonna valueJson verrà impostata su null e la colonna del valore conterrà il valore.

Esempio di database di stato

Di seguito sono riportati alcuni esempi di chiavi e relativi valori del database di stato dell'esempio Car Dealer.

chiave value valueJson
abg1234 nullo {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
abg1235 nullo {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
ser1236 nullo {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}
bra1238 nullo {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "nome": "pastiglia freno 4200", "proprietario": "Detroit Auto", "richiamo": falso, "recallDate": 1502688979}
dtrt10001 nullo {"docType": "veicolo", "chassisNumber": "dtrt10001", "fabbricante": "Detroit Auto", "modello": "una coupé", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "proprietario": "Sam Dealer", "richiamo": falso, "recallDate": 1502688979

Rich query nella console

Gli amministratori possono eseguire e analizzare query avanzate dalla console.

  1. Andare alla console e selezionare la scheda Canali.
  2. Nella tabella Canali individuare il canale in cui si desidera eseguire una query, fare clic sul pulsante Altre azioni dei canali, quindi fare clic su Analizza query multimediali. Viene visualizzata la finestra di dialogo Analizza query RTF.
  3. Per eseguire una query RTF sul database di stato, selezionare Esecuzione query.
    1. Per Chaincode, selezionare il codice concatenato distribuito nel canale su cui si desidera eseguire la query.
    2. Per Peer, selezionare il peer to query.
      Sono disponibili solo i peer nell'organizzazione corrente che eseguono il codice concatenato selezionato.
    3. Per Query Rich, immettere la query RTF da eseguire e analizzare.
      Il formato della query deve seguire la sintassi rich query. Per ulteriori informazioni sulla sintassi Rich Query, vedere Sintassi Rich Query supportata.
    4. Per Limite righe risultato, spostare il dispositivo di scorrimento al numero massimo di righe dei risultati da recuperare. È possibile recuperare fino a 50 righe di risultati.
  4. Per ottenere il piano di esecuzione di una query, selezionare Dichiarazione piano query. Un piano di esecuzione delle query è la sequenza di operazioni eseguite per eseguire la query.
    1. Per Chaincode, selezionare il codice concatenato distribuito nel canale su cui si desidera eseguire la query.
    2. Per Peer, selezionare il peer to query.
    3. Per Raccolta, selezionare il database di stato o la raccolta di dati privati.
    4. Per Rich Query, immettere la query Rich.
      La parola chiave explain non è richiesta per questa query.
      Ad esempio: select * from <state>
  5. Fare clic su Esegui. Il campo Risultati mostra la tabella dei risultati della query o il piano di esecuzione. Per esportare la tabella dei risultati come file .csv, fare clic su Esporta.
    La dimensione della tabella dei risultati è limitata a 1 MB. Potrebbe essere necessario perfezionare la query per evitare di superare questo limite.

Sintassi rich query supportata

Oracle Blockchain Platform supporta due tipi di sintassi rich query che è possibile utilizzare per eseguire query sul database di stato: SQL rich query e rich query CouchDB.

Sintassi query SQL Rich

Le estensioni JSON di Berkeley DB sono sotto forma di funzioni SQL.

Operazioni preliminari

Tenere presenti le informazioni riportate di seguito.

  • È possibile accedere solo al codice concatenato canale (<STATE>) da cui si sta eseguendo la query.
  • È supportata solo l'istruzione SELECT.
  • Impossibile modificare la tabella del database di stato.
  • Un'espressione di query RTF può avere una sola istruzione SELECT.
  • Gli esempi in questo argomento sono solo alcuni modi in cui è possibile scrivere la query RTF. Si dispone dell'accesso alla sintassi SQL completa per eseguire query su un database SQL.
  • Hai accesso all'estensione JSON1 (estensione SQLite). Vedere JSON1 Extension e SQL As Understand by SQLite.

Per ulteriori informazioni sulla scrittura e il test dei codici concatenati, vedere Sviluppa codici concatenati.

Come fare riferimento al database di stato nelle query

Il nome della tabella del database di stato è gestito internamente da Oracle Blockchain Platform, pertanto non è necessario conoscere il nome fisico del database di stato quando si scrive un codice concatenato.

Utilizzare, invece, l'alias <STATE> per fare riferimento al nome della tabella. Ad esempio: select key, value from <STATE>.

Si noti che l'alias <STATE> non fa distinzione tra maiuscole e minuscole, pertanto è possibile utilizzare <state>, <STATE> o <StAtE>.

Recupera tutte le chiavi

Utilizzare questa sintassi:

SELECT key FROM <STATE>

Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Concessionario auto, verrà visualizzato il seguente elenco di chiavi:

chiave

abg1234

abg1235

ser1236

bra1238

dtrt10001

Recupera tutte le chiavi e tutti i valori ordinati in ordine alfabetico per chiave

Utilizzare questa sintassi:

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

Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:

serialNumber details
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, "nome": "pastiglia freno 4200", "proprietario": "Detroit Auto", "richiamo": falso, "recallDate": 1502688979}
dtrt10001 {"docType": "veicolo", "chassisNumber": "dtrt10001", "fabbricante": "Detroit Auto", "modello": "una coupé", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "proprietario": "Sam Dealer", "richiamo": falso, "recallDate": 1502688979
ser1236 {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979}

Recupera tutte le chiavi e i valori a partire da "abg"

Utilizzare questa sintassi:

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

Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:

serialNumber details
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"}

Recupera tutte le chiavi con valori che contengono una parte del veicolo di proprietà di "Detroit Auto"

Utilizzare questa sintassi:

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

Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Concessionario auto, verrà visualizzato il seguente elenco di chiavi:

chiave

abg1234

abg1235

ser1236

bra1238

Recupera modello e produttore per tutte le auto possedute da "Sam Dealer"

Utilizzare questa sintassi:

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'

Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:

modello produttore
un coupé Detroit Auto

Se il valore di stato è un array JSON, è possibile utilizzare questa sintassi per recuperare il modello e il produttore per tutte le auto di proprietà di "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'

Sintassi rich query CouchDB

Utilizzare le informazioni riportate in questo argomento se si sta eseguendo la migrazione dei codici concatenati contenenti la sintassi CouchDB in Oracle Blockchain Platform o se è necessario scrivere codici concatenati da installare sui peer di Hyperledger Fabric che partecipano a una rete Oracle Blockchain Platform.

Se stai scrivendo un nuovo codice concatenato, Oracle consiglia di utilizzare query SQL rich per sfruttare i vantaggi delle prestazioni offerti da Oracle Blockchain Platform con Berkeley DB.

Per ulteriori informazioni sulla scrittura e il test dei codici concatenati, vedere Sviluppa codici concatenati.

Parametri query e sintassi selettore non supportati

Oracle Blockchain Platform non supporta il parametro use_index. Se utilizzato, Oracle Blockchain Platform ignora questo parametro e selezionerà automaticamente gli indici definiti nel file StateDB in questione.

Parametro Type Descrizione
use_index json Indica a una query di utilizzare un indice specifico.

Recupera tutti i modelli, i produttori e i proprietari di auto e li ordina per proprietario

Usare l'espressione seguente:

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

Recupera modello e produttore per tutte le auto possedute da "Sam Dealer"

Usare l'espressione seguente:

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

Indici database di stato

Il database di stato può contenere una grande quantità di dati. In questi casi Oracle Blockchain Platform utilizza gli indici per migliorare l'accesso ai dati.

Indici predefiniti

Quando viene distribuito un codice concatenato, Oracle Blockchain Platform crea due indici.

  • Indice chiave: creato nella colonna chiave.

  • Indice dei valori: creato nella colonna dei valori.

Indici personalizzati

In alcuni casi potrebbe essere necessario creare indici personalizzati. Per definire questi indici, utilizzare qualsiasi espressione risolvibile nel contesto della tabella di stato. Gli indici personalizzati creati rispetto a Berkeley DB si basano sulla sintassi SQLite, ma seguono comunque la stessa implementazione CouchDB fornita da Hyperledger Fabric.

È possibile utilizzare indici personalizzati per migliorare notevolmente le prestazioni delle istruzioni WHERE e ORDER BY in set di dati di grandi dimensioni. Poiché l'utilizzo di indici personalizzati rallenta l'inserimento dei dati, utilizzarli con cautela.

Ogni indice personalizzato è definito come un array di espressioni, che supportano indici composti, espressi come documento JSON all'interno di un file. Esiste un indice per file. È necessario raggruppare questo file con il codice concatenato in una cartella denominata indexes nella struttura di directory seguente: statedb/relationaldb/indexes. Per ulteriori informazioni, vedere Come aggiungere gli indici CouchDB durante l'installazione del codice concatenato.

Indici personalizzati di esempio

Gli esempi di indici personalizzati in questa sezione utilizzano l'esempio Rivenditore auto.

Esempio 1: questo esempio indicizza l'uso dell'espressione json_extract nel contesto delle espressioni WHERE e ORDER BY.

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

Ad esempio:

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

Esempio 2: questo esempio indicizza l'uso composto delle due espressioni json_extract nel contesto delle espressioni WHERE e ORDER BY.

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

Ad esempio:

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

Esempio 3: in questo esempio viene creato sia l'indice descritto nell'esempio 1 che l'indice descritto nell'esempio 2. Ogni struttura JSON deve essere inclusa in un file separato. Ogni file descrive un singolo indice: un indice semplice come l'esempio 1 o un indice composto come l'esempio 2.

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

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

Nell'esempio seguente, Index 2 viene applicato all'espressione AND nella parte WHERE della query, mentre Index 1 viene applicato all'espressione ORDER BY:

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

Formato documento JSON

Il documento JSON deve essere nel seguente formato:

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

Ad esempio:

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

Differenze nella convalida delle query complesse

In alcuni casi, la query avanzata Hyperledger Fabric standard con CouchDB e la query avanzata Oracle Berkeley DB funzionano in modo diverso.

In Hyperledger Fabric standard con CouchDB, ogni coppia di chiavi e valori restituita dalla query viene aggiunta al set di lettura della transazione ed è convalidata al momento della convalida e senza rieseguire la query. In Berkeley DB, la coppia di chiave e valore restituita non viene aggiunta al set di lettura, ma il risultato della query RTF viene sottoposto a hash in un albero Merkle e convalidato in base alla riesecuzione della query al momento della convalida.

Hyperledger Fabric nativo non fornisce la protezione dei dati per query avanzate. Tuttavia, Berkeley DB contiene funzionalità che proteggono e convalidano la query RTF aggiungendo il valore hash dell'albero Merkle nel set di lettura, rieseguendo la query RTF e nella fase di convalida ricalcolando il valore dell'albero Merkle. Si noti che, poiché la convalida è più accurata in Oracle Blockchain Platform con Berkeley DB, a volte i richiami dei codici concatenati vengono contrassegnati per letture fantasma più frequenti.