diff --git a/api.go b/api.go index 75becc899..37d385791 100644 --- a/api.go +++ b/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 { diff --git a/handler.go b/handler.go index 6276ac535..ee9a7d8b5 100644 --- a/handler.go +++ b/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.