Repository: codenotary/immudb
File: pkg/database/all_ops.go (Go)

Code before:
		for i, op := range req.Operations {

			e := &store.EntrySpec{}

			switch x := op.Operation.(type) {

			case *schema.Op_Kv:
				kmap[sha256.Sum256(x.Kv.Key)] = true

				if len(x.Kv.Key) == 0 {
					return nil, store.ErrIllegalArguments
				}

				e = EncodeEntrySpec(x.Kv.Key, schema.KVMetadataFromProto(x.Kv.Metadata), x.Kv.Value)

			case *schema.Op_Ref:
				if len(x.Ref.Key) == 0 || len(x.Ref.ReferencedKey) == 0 {
					return nil, store.ErrIllegalArguments
				}

				if x.Ref.AtTx > 0 && !x.Ref.BoundRef {
					return nil, store.ErrIllegalArguments
				}

				if req.NoWait && (x.Ref.AtTx != 0 || !x.Ref.BoundRef) {
					return nil, ErrNoWaitOperationMustBeSelfContained
				}

				_, exists := kmap[sha256.Sum256(x.Ref.ReferencedKey)]

				if req.NoWait && !exists {
					return nil, ErrNoWaitOperationMustBeSelfContained
				}

				if !req.NoWait {
					// check key does not exists or it's already a reference
					entry, err := d.getAt(EncodeKey(x.Ref.Key), 0, 0, index, tx)
					if err != nil && err != store.ErrKeyNotFound {
						return nil, err
					}
					if entry != nil && entry.ReferencedBy == nil {
						return nil, ErrFinalKeyCannotBeConvertedIntoReference
					}

					if !exists || x.Ref.AtTx > 0 {
						// check referenced key exists and it's not a reference
						refEntry, err := d.getAt(EncodeKey(x.Ref.ReferencedKey), x.Ref.AtTx, 0, index, tx)
						if err != nil {
							return nil, err
						}
						if refEntry.ReferencedBy != nil {

Review comment (suggestion):
Maybe we should add some more descriptive info here:

```suggestion
					return nil, fmt.Errorf(
					    "%w: can only set references to keys added within same transaction, please use bound references with AtTx set to 0",
					    ErrNoWaitOperationMustBeSelfContained,
					)
```

Code after:

		for i, op := range req.Operations {

			e := &store.EntrySpec{}

			switch x := op.Operation.(type) {

			case *schema.Op_Kv:
				kmap[sha256.Sum256(x.Kv.Key)] = true

				if len(x.Kv.Key) == 0 {
					return nil, store.ErrIllegalArguments
				}

				e = EncodeEntrySpec(x.Kv.Key, schema.KVMetadataFromProto(x.Kv.Metadata), x.Kv.Value)

			case *schema.Op_Ref:
				if len(x.Ref.Key) == 0 || len(x.Ref.ReferencedKey) == 0 {
					return nil, store.ErrIllegalArguments
				}

				if x.Ref.AtTx > 0 && !x.Ref.BoundRef {
					return nil, store.ErrIllegalArguments
				}

				if req.NoWait && (x.Ref.AtTx != 0 || !x.Ref.BoundRef) {
					return nil, fmt.Errorf(
						"%w: can only set references to keys added within same transaction, please use bound references with AtTx set to 0",
						ErrNoWaitOperationMustBeSelfContained)
				}

				_, exists := kmap[sha256.Sum256(x.Ref.ReferencedKey)]

				if req.NoWait && !exists {
					return nil, fmt.Errorf(
						"%w: can not create a reference to a key that was not set in the same transaction",
						ErrNoWaitOperationMustBeSelfContained)
				}

				if !req.NoWait {
					// check key does not exists or it's already a reference
					entry, err := d.getAt(EncodeKey(x.Ref.Key), 0, 0, index, tx)
					if err != nil && err != store.ErrKeyNotFound {
						return nil, err
					}
					if entry != nil && entry.ReferencedBy == nil {
						return nil, ErrFinalKeyCannotBeConvertedIntoReference
					}

					if !exists || x.Ref.AtTx > 0 {
						// check referenced key exists and it's not a reference