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

Code before:
							return nil, err
						}
						if refEntry.ReferencedBy != nil {
							return nil, ErrReferencedKeyCannotBeAReference
						}
					}
				}

				// reference arguments are converted in regular key value items and then atomically inserted
				if x.Ref.BoundRef && x.Ref.AtTx == 0 {
					e = EncodeReference(x.Ref.Key, nil, x.Ref.ReferencedKey, txID)
				} else {
					e = EncodeReference(x.Ref.Key, nil, x.Ref.ReferencedKey, x.Ref.AtTx)
				}

			case *schema.Op_ZAdd:
				if len(x.ZAdd.Set) == 0 || len(x.ZAdd.Key) == 0 {
					return nil, store.ErrIllegalArguments
				}

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

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

				_, exists := kmap[sha256.Sum256(x.ZAdd.Key)]

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

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

				// zAdd arguments are converted in regular key value items and then atomically inserted
				key := EncodeKey(x.ZAdd.Key)

				if x.ZAdd.BoundRef && x.ZAdd.AtTx == 0 {

Review comment (suggestion):
This could use a better error message, similarly to the `Op_Ref` operation.

Code after:

					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 {
							return nil, ErrReferencedKeyCannotBeAReference
						}
					}
				}

				// reference arguments are converted in regular key value items and then atomically inserted
				if x.Ref.BoundRef && x.Ref.AtTx == 0 {
					e = EncodeReference(x.Ref.Key, nil, x.Ref.ReferencedKey, txID)
				} else {
					e = EncodeReference(x.Ref.Key, nil, x.Ref.ReferencedKey, x.Ref.AtTx)
				}

			case *schema.Op_ZAdd:
				if len(x.ZAdd.Set) == 0 || len(x.ZAdd.Key) == 0 {
					return nil, store.ErrIllegalArguments
				}

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

				if req.NoWait && (x.ZAdd.AtTx != 0 || !x.ZAdd.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.ZAdd.Key)]

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

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