mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-09 04:17:51 +00:00
sort import values stably without using sort.Stable
sort.Stable has horrible runtime -- O(n*logn*logn) -- but if we don't use sort.Stable, our logic for ensuring that we apply the "last" value for a given column is actually completely wrong in the first place.
This commit is contained in:
parent
7572acb450
commit
4bad5defb6
2 changed files with 26 additions and 2 deletions
8
api.go
8
api.go
|
|
@ -1568,7 +1568,15 @@ func (api *API) ImportValueWithTx(ctx context.Context, qcx *Qcx, req *ImportValu
|
|||
}
|
||||
|
||||
if !options.Presorted {
|
||||
// horrible hackery: we implement a secondary key so we can
|
||||
// get a stable sort without using sort.Stable
|
||||
req.scratch = make([]int, len(req.ColumnIDs))
|
||||
for i := range req.scratch {
|
||||
req.scratch[i] = i
|
||||
}
|
||||
sort.Sort(req)
|
||||
// don't keep that list around since we don't need it anymore
|
||||
req.scratch = nil
|
||||
}
|
||||
isLocalQcx := false
|
||||
if qcx == nil {
|
||||
|
|
|
|||
20
handler.go
20
handler.go
|
|
@ -123,6 +123,7 @@ type ImportValueRequest struct {
|
|||
TimestampValues []time.Time
|
||||
StringValues []string
|
||||
Clear bool
|
||||
scratch []int // scratch space to allow us to get a stable sort in reasonable time
|
||||
}
|
||||
|
||||
// AtomicRecord applies all its Ivr and Ivr atomically, in a Tx.
|
||||
|
|
@ -138,8 +139,20 @@ type AtomicRecord struct {
|
|||
Ir []*ImportRequest // other field types, e.g. single bit
|
||||
}
|
||||
|
||||
func (ivr *ImportValueRequest) Len() int { return len(ivr.ColumnIDs) }
|
||||
func (ivr *ImportValueRequest) Less(i, j int) bool { return ivr.ColumnIDs[i] < ivr.ColumnIDs[j] }
|
||||
func (ivr *ImportValueRequest) Len() int { return len(ivr.ColumnIDs) }
|
||||
func (ivr *ImportValueRequest) Less(i, j int) bool {
|
||||
if ivr.ColumnIDs[i] < ivr.ColumnIDs[j] {
|
||||
return true
|
||||
}
|
||||
if ivr.ColumnIDs[i] > ivr.ColumnIDs[j] {
|
||||
return false
|
||||
}
|
||||
if len(ivr.scratch) > 0 {
|
||||
return ivr.scratch[i] < ivr.scratch[j]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ivr *ImportValueRequest) Swap(i, j int) {
|
||||
ivr.ColumnIDs[i], ivr.ColumnIDs[j] = ivr.ColumnIDs[j], ivr.ColumnIDs[i]
|
||||
if len(ivr.Values) > 0 {
|
||||
|
|
@ -151,6 +164,9 @@ func (ivr *ImportValueRequest) Swap(i, j int) {
|
|||
} else if len(ivr.StringValues) > 0 {
|
||||
ivr.StringValues[i], ivr.StringValues[j] = ivr.StringValues[j], ivr.StringValues[i]
|
||||
}
|
||||
if len(ivr.scratch) > 0 {
|
||||
ivr.scratch[i], ivr.scratch[j] = ivr.scratch[j], ivr.scratch[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Validate ensures that the payload of the request is valid.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue