mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 00:55:55 +00:00
copy things rows after getting them and before their finishers during writes
When a qcx is a write, every Tx under it closes immediately, thus invalidating all returned data. Thus, if you do a Not() inside a Store(), you're doing a difference on an existence row and some other row call... and both of those rows were run, individually, as separate transactions that got invalidated the moment they were fetched. Oops.
This commit is contained in:
parent
4279e2cb2d
commit
29f5f6d7c2
1 changed files with 20 additions and 2 deletions
22
executor.go
22
executor.go
|
|
@ -4493,7 +4493,11 @@ func (e *executor) executeRowShard(ctx context.Context, qcx *Qcx, index string,
|
|||
return nil, err
|
||||
}
|
||||
defer finisher(&err0)
|
||||
return frag.row(tx, rowID)
|
||||
row, err := frag.row(tx, rowID)
|
||||
if qcx.write && err == nil {
|
||||
row = row.Clone()
|
||||
}
|
||||
return row, err
|
||||
}
|
||||
|
||||
// If no quantum exists then return an empty bitmap.
|
||||
|
|
@ -4532,15 +4536,21 @@ func (e *executor) executeRowShard(ctx context.Context, qcx *Qcx, index string,
|
|||
if len(rows) == 0 {
|
||||
return &Row{}, nil
|
||||
} else if len(rows) == 1 {
|
||||
if qcx.write {
|
||||
return rows[0].Clone(), nil
|
||||
}
|
||||
return rows[0], nil
|
||||
}
|
||||
row := rows[0].Union(rows[1:]...)
|
||||
if qcx.write {
|
||||
row = row.Clone()
|
||||
}
|
||||
return row, nil
|
||||
|
||||
}
|
||||
|
||||
// executeRowBSIGroupShard executes a range(bsiGroup) call for a local shard.
|
||||
func (e *executor) executeRowBSIGroupShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64) (_ *Row, err0 error) {
|
||||
func (e *executor) executeRowBSIGroupShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64) (cloneable *Row, err0 error) {
|
||||
span, _ := tracing.StartSpanFromContext(ctx, "Executor.executeRowBSIGroupShard")
|
||||
defer span.Finish()
|
||||
|
||||
|
|
@ -4572,6 +4582,11 @@ func (e *executor) executeRowBSIGroupShard(ctx context.Context, qcx *Qcx, index
|
|||
return nil, err
|
||||
}
|
||||
defer finisher(&err0)
|
||||
defer func() {
|
||||
if qcx.write && cloneable != nil {
|
||||
cloneable = cloneable.Clone()
|
||||
}
|
||||
}()
|
||||
|
||||
// EQ null _exists - frag.NotNull()
|
||||
// NEQ null frag.NotNull()
|
||||
|
|
@ -4822,6 +4837,9 @@ func (e *executor) executeNotShard(ctx context.Context, qcx *Qcx, index string,
|
|||
if existenceRow, err = existenceFrag.row(tx, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if qcx.write {
|
||||
existenceRow = existenceRow.Clone()
|
||||
}
|
||||
}
|
||||
// the finishers returned by a write tx, which we might be in if there's
|
||||
// a higher-level write in this call OR ANY OTHER CALL, are safe to
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue