mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-09-19 07:29:23 +08:00
limit with offset
This commit is contained in:
@@ -350,7 +350,8 @@ func (e *SQLEngine) executeAggregationQuery(ctx context.Context, hybridScanner *
|
|||||||
// executeAggregationQueryWithPlan handles SELECT queries with aggregation functions and populates execution plan
|
// executeAggregationQueryWithPlan handles SELECT queries with aggregation functions and populates execution plan
|
||||||
func (e *SQLEngine) executeAggregationQueryWithPlan(ctx context.Context, hybridScanner *HybridMessageScanner, aggregations []AggregationSpec, stmt *SelectStatement, plan *QueryExecutionPlan) (*QueryResult, error) {
|
func (e *SQLEngine) executeAggregationQueryWithPlan(ctx context.Context, hybridScanner *HybridMessageScanner, aggregations []AggregationSpec, stmt *SelectStatement, plan *QueryExecutionPlan) (*QueryResult, error) {
|
||||||
// Parse LIMIT and OFFSET for aggregation results (do this first)
|
// Parse LIMIT and OFFSET for aggregation results (do this first)
|
||||||
limit := 0
|
// Use -1 to distinguish "no LIMIT" from "LIMIT 0"
|
||||||
|
limit := -1
|
||||||
offset := 0
|
offset := 0
|
||||||
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
||||||
if limitExpr, ok := stmt.Limit.Rowcount.(*SQLVal); ok && limitExpr.Type == IntVal {
|
if limitExpr, ok := stmt.Limit.Rowcount.(*SQLVal); ok && limitExpr.Type == IntVal {
|
||||||
@@ -391,29 +392,31 @@ func (e *SQLEngine) executeAggregationQueryWithPlan(ctx context.Context, hybridS
|
|||||||
if isDebugMode(ctx) {
|
if isDebugMode(ctx) {
|
||||||
fmt.Printf("Using fast hybrid statistics for aggregation (parquet stats + live log counts)\n")
|
fmt.Printf("Using fast hybrid statistics for aggregation (parquet stats + live log counts)\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply OFFSET and LIMIT to fast path results too
|
// Apply OFFSET and LIMIT to fast path results too
|
||||||
if offset > 0 || limit > 0 {
|
// Limit semantics: -1 = no limit, 0 = LIMIT 0 (empty), >0 = limit to N rows
|
||||||
|
if offset > 0 || limit >= 0 {
|
||||||
rows := fastResult.Rows
|
rows := fastResult.Rows
|
||||||
// Apply OFFSET first
|
// Handle LIMIT 0 first
|
||||||
if offset > 0 {
|
if limit == 0 {
|
||||||
if offset >= len(rows) {
|
rows = [][]sqltypes.Value{}
|
||||||
rows = [][]sqltypes.Value{}
|
} else {
|
||||||
} else {
|
// Apply OFFSET first
|
||||||
rows = rows[offset:]
|
if offset > 0 {
|
||||||
|
if offset >= len(rows) {
|
||||||
|
rows = [][]sqltypes.Value{}
|
||||||
|
} else {
|
||||||
|
rows = rows[offset:]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
// Apply LIMIT after OFFSET (only if limit > 0)
|
||||||
// Apply LIMIT after OFFSET
|
if limit > 0 && len(rows) > limit {
|
||||||
if limit >= 0 { // Handle LIMIT 0 case
|
|
||||||
if limit == 0 {
|
|
||||||
rows = [][]sqltypes.Value{}
|
|
||||||
} else if len(rows) > limit {
|
|
||||||
rows = rows[:limit]
|
rows = rows[:limit]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fastResult.Rows = rows
|
fastResult.Rows = rows
|
||||||
}
|
}
|
||||||
|
|
||||||
return fastResult, nil
|
return fastResult, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -484,22 +487,24 @@ func (e *SQLEngine) executeAggregationQueryWithPlan(ctx context.Context, hybridS
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply OFFSET and LIMIT to aggregation results
|
// Apply OFFSET and LIMIT to aggregation results
|
||||||
|
// Limit semantics: -1 = no limit, 0 = LIMIT 0 (empty), >0 = limit to N rows
|
||||||
rows := [][]sqltypes.Value{row}
|
rows := [][]sqltypes.Value{row}
|
||||||
if offset > 0 || limit > 0 {
|
if offset > 0 || limit >= 0 {
|
||||||
// Apply OFFSET first
|
// Handle LIMIT 0 first
|
||||||
if offset > 0 {
|
if limit == 0 {
|
||||||
if offset >= len(rows) {
|
rows = [][]sqltypes.Value{}
|
||||||
rows = [][]sqltypes.Value{}
|
} else {
|
||||||
} else {
|
// Apply OFFSET first
|
||||||
rows = rows[offset:]
|
if offset > 0 {
|
||||||
|
if offset >= len(rows) {
|
||||||
|
rows = [][]sqltypes.Value{}
|
||||||
|
} else {
|
||||||
|
rows = rows[offset:]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Apply LIMIT after OFFSET
|
// Apply LIMIT after OFFSET (only if limit > 0)
|
||||||
if limit >= 0 { // Handle LIMIT 0 case
|
if limit > 0 && len(rows) > limit {
|
||||||
if limit == 0 {
|
|
||||||
rows = [][]sqltypes.Value{}
|
|
||||||
} else if len(rows) > limit {
|
|
||||||
rows = rows[:limit]
|
rows = rows[:limit]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1416,7 +1416,8 @@ func (e *SQLEngine) executeSelectStatement(ctx context.Context, stmt *SelectStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse LIMIT and OFFSET clauses
|
// Parse LIMIT and OFFSET clauses
|
||||||
limit := 0
|
// Use -1 to distinguish "no LIMIT" from "LIMIT 0"
|
||||||
|
limit := -1
|
||||||
offset := 0
|
offset := 0
|
||||||
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
||||||
switch limitExpr := stmt.Limit.Rowcount.(type) {
|
switch limitExpr := stmt.Limit.Rowcount.(type) {
|
||||||
@@ -1605,7 +1606,8 @@ func (e *SQLEngine) executeSelectStatementWithBrokerStats(ctx context.Context, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse LIMIT and OFFSET clauses
|
// Parse LIMIT and OFFSET clauses
|
||||||
limit := 0
|
// Use -1 to distinguish "no LIMIT" from "LIMIT 0"
|
||||||
|
limit := -1
|
||||||
offset := 0
|
offset := 0
|
||||||
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
if stmt.Limit != nil && stmt.Limit.Rowcount != nil {
|
||||||
switch limitExpr := stmt.Limit.Rowcount.(type) {
|
switch limitExpr := stmt.Limit.Rowcount.(type) {
|
||||||
|
@@ -233,25 +233,26 @@ func (hms *HybridMessageScanner) ScanWithStats(ctx context.Context, options Hybr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply final OFFSET and LIMIT processing (done once at the end)
|
// Apply final OFFSET and LIMIT processing (done once at the end)
|
||||||
|
// Limit semantics: -1 = no limit, 0 = LIMIT 0 (empty), >0 = limit to N rows
|
||||||
if options.Offset > 0 || options.Limit >= 0 {
|
if options.Offset > 0 || options.Limit >= 0 {
|
||||||
// Handle LIMIT 0 special case - return empty result immediately
|
// Handle LIMIT 0 special case first
|
||||||
if options.Limit == 0 {
|
if options.Limit == 0 {
|
||||||
results = []HybridScanResult{}
|
return []HybridScanResult{}, stats, nil
|
||||||
} else {
|
}
|
||||||
// Apply OFFSET first
|
|
||||||
if options.Offset > 0 {
|
|
||||||
if options.Offset >= len(results) {
|
|
||||||
results = []HybridScanResult{}
|
|
||||||
} else {
|
|
||||||
results = results[options.Offset:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply LIMIT after OFFSET
|
// Apply OFFSET first
|
||||||
if options.Limit > 0 && len(results) > options.Limit {
|
if options.Offset > 0 {
|
||||||
results = results[:options.Limit]
|
if options.Offset >= len(results) {
|
||||||
|
results = []HybridScanResult{}
|
||||||
|
} else {
|
||||||
|
results = results[options.Offset:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply LIMIT after OFFSET (only if limit > 0)
|
||||||
|
if options.Limit > 0 && len(results) > options.Limit {
|
||||||
|
results = results[:options.Limit]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results, stats, nil
|
return results, stats, nil
|
||||||
|
Reference in New Issue
Block a user