PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/datastore

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
datastore
Namespace
g17khqpukees4237dtn3astzapmp462vjhsz6st4
Files
11 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/datastore
gno
0.9

Files (11)

  • README.mdmarkdown
  • gnomod.tomltoml
  • datastore.gnogno
  • index.gnogno
  • query_options.gnogno
  • query.gnogno
  • record.gnogno
  • schema_options.gnogno
  • schema.gnogno
  • storage_options.gnogno
  • storage.gnogno
  • record.gnogno
    1package datastore23import (4	"errors"56	"gno.land/p/moul/collection/v0"7	"gno.land/p/nt/bptree/v0"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    "gno.land/p/nt/seqid/v0"
    9)
    10
    11// ErrUndefinedField indicates that a field in not defined in a record's schema.
    12var ErrUndefinedField = errors.New("undefined field")
    13
    14type (
    15 // Record stores values for one or more fields.
    16 Record interface {
    17 ReadOnlyRecord
    18
    19 // Set assings a value to a record field.
    20 // If the field doesn't exist it's created if the underlying schema allows it.
    21 // Storage schema can optionally be strict in which case no new fields other than
    22 // the ones that were previously defined are allowed.
    23 Set(field string, value interface{}) error
    24
    25 // Save assigns an ID to newly created records and update storage indexes.
    26 Save() bool
    27 }
    28
    29 // ReadOnlyRecord defines an interface for read-only records.
    30 ReadOnlyRecord interface {
    31 // ID returns record's ID
    32 ID() uint64
    33
    34 // Key returns a string representation of the record's ID.
    35 // It's used to be able to search records within the ID index.
    36 Key() string
    37
    38 // Type returns the record's type.
    39 Type() string
    40
    41 // Fields returns the list of the record's field names.
    42 Fields() []string
    43
    44 // IsEmpty checks if the record has no values.
    45 IsEmpty() bool
    46
    47 // HasField checks if the record has a specific field.
    48 HasField(name string) bool
    49
    50 // Get returns the value of a record's field.
    51 Get(field string) (value interface{}, found bool)
    52
    53 // MustGet returns the value of a record's field or panics when the field is not found.
    54 MustGet(field string) interface{}
    55 }
    56
    57 // RecordIterFn defines a type for record iteration functions.
    58 RecordIterFn func(Record) (stop bool)
    59
    60 // Recordset defines an interface that allows iterating multiple records.
    61 Recordset interface {
    62 // Iterate iterates records in order.
    63 Iterate(fn RecordIterFn) (stopped bool)
    64
    65 // ReverseIterate iterates records in reverse order.
    66 ReverseIterate(fn RecordIterFn) (stopped bool)
    67
    68 // Size returns the number of records in the recordset.
    69 Size() int
    70 }
    71)
    72
    73type record struct {
    74 id uint64
    75 schema *Schema
    76 collection *collection.Collection
    77 values *bptree.BPTree // string(field index) -> interface{}
    78}
    79
    80// ID returns record's ID
    81func (r record) ID() uint64 {
    82 return r.id
    83}
    84
    85// Key returns a string representation of the record's ID.
    86// It's used to be able to search records within the ID index.
    87func (r record) Key() string {
    88 return seqid.ID(r.id).String()
    89}
    90
    91// Type returns the record's type.
    92func (r record) Type() string {
    93 return r.schema.Name()
    94}
    95
    96// Fields returns the list of the record's field names.
    97func (r record) Fields() []string {
    98 return r.schema.Fields()
    99}
    100
    101// IsEmpty checks if the record has no values.
    102func (r record) IsEmpty() bool {
    103 return r.values.Size() == 0
    104}
    105
    106// HasField checks if the record has a specific field.
    107func (r record) HasField(name string) bool {
    108 return r.schema.HasField(name)
    109}
    110
    111// Set assings a value to a record field.
    112// If the field doesn't exist it's created if the underlying schema allows it.
    113// Storage schema can optionally be strict in which case no new fields other than
    114// the ones that were previously defined are allowed.
    115func (r *record) Set(field string, value interface{}) error {
    116 i := r.schema.GetFieldIndex(field)
    117 if i == -1 {
    118 if r.schema.IsStrict() {
    119 return ErrUndefinedField
    120 }
    121
    122 i, _ = r.schema.AddField(field, nil)
    123 }
    124
    125 key := castIntToKey(i)
    126 r.values.Set(key, value)
    127 return nil
    128}
    129
    130// Get returns the value of a record's field.
    131func (r record) Get(field string) (value interface{}, found bool) {
    132 i := r.schema.GetFieldIndex(field)
    133 if i == -1 {
    134 return nil, false
    135 }
    136
    137 key := castIntToKey(i)
    138 if r.values.Has(key) {
    139 return r.values.Get(key), true
    140 }
    141 return nil, false
    142}
    143
    144// MustGet returns the value of a record's field or panics when the field is not found.
    145func (r record) MustGet(field string) interface{} {
    146 v, found := r.Get(field)
    147 if !found {
    148 panic("field not found: " + field)
    149 }
    150 return v
    151}
    152
    153// Save assigns an ID to newly created records and update storage indexes.
    154func (r *record) Save() bool {
    155 if r.id == 0 {
    156 r.id = r.collection.Set(r)
    157 return r.id != 0
    158 }
    159 return r.collection.Update(r.id, r)
    160}
    161
    162type recordset struct {
    163 query Query
    164 records bptree.ITree
    165 keys []string
    166 size int
    167}
    168
    169// Iterate iterates records in order.
    170func (rs recordset) Iterate(fn RecordIterFn) (stopped bool) {
    171 if rs.isUsingCustomIndex() {
    172 for _, k := range rs.keys {
    173 r, ok := rs.records.Get(k).(Record)
    174 if !ok {
    175 continue
    176 }
    177
    178 if fn(r) {
    179 return true
    180 }
    181 }
    182
    183 return false
    184 }
    185
    186 offset := rs.query.Offset()
    187 count := rs.query.Size()
    188 if count == 0 {
    189 count = rs.records.Size()
    190 }
    191
    192 return rs.records.IterateByOffset(offset, count, func(_ string, v interface{}) bool {
    193 return fn(v.(Record))
    194 })
    195}
    196
    197// ReverseIterate iterates records in reverse order.
    198func (rs recordset) ReverseIterate(fn RecordIterFn) (stopped bool) {
    199 if rs.isUsingCustomIndex() {
    200 for i := len(rs.keys) - 1; i >= 0; i-- {
    201 r, ok := rs.records.Get(rs.keys[i]).(Record)
    202 if !ok {
    203 continue
    204 }
    205
    206 if fn(r) {
    207 return true
    208 }
    209 }
    210
    211 return false
    212 }
    213
    214 offset := rs.query.Offset()
    215 count := rs.query.Size()
    216 if count == 0 {
    217 count = rs.records.Size()
    218 }
    219
    220 return rs.records.ReverseIterateByOffset(offset, count, func(_ string, v interface{}) bool {
    221 return fn(v.(Record))
    222 })
    223}
    224
    225// Size returns the number of records in the recordset.
    226func (rs recordset) Size() int {
    227 return rs.size
    228}
    229
    230func (rs recordset) isUsingCustomIndex() bool {
    231 return rs.query.IndexName() != collection.IDIndex
    232}
    233