MCPcopy Create free account
hub / github.com/bytebase/bytebase / rewriteSelectLimit

Function rewriteSelectLimit

backend/plugin/db/pg/query.go:251–278  ·  view source on GitHub ↗

rewriteSelectLimit adds or adjusts the LIMIT clause of a SELECT statement using byte-offset positions from the omni AST to surgically edit the original SQL text.

(sql string, sel *ast.SelectStmt, limitCount int)

Source from the content-addressed store, hash-verified

249// rewriteSelectLimit adds or adjusts the LIMIT clause of a SELECT statement
250// using byte-offset positions from the omni AST to surgically edit the original SQL text.
251func rewriteSelectLimit(sql string, sel *ast.SelectStmt, limitCount int) (string, error) {
252 if sel.LimitCount != nil {
253 // Already has LIMIT — replace the value if ours is lower.
254 existingLimit := extractIntFromNode(sel.LimitCount)
255 if existingLimit > 0 && existingLimit <= limitCount {
256 return sql, nil // existing limit is already lower or equal, keep it
257 }
258 loc := nodeLocOf(sel.LimitCount)
259 if loc.Start >= 0 && loc.End > loc.Start && loc.End <= len(sql) {
260 return sql[:loc.Start] + fmt.Sprintf("%d", limitCount) + sql[loc.End:], nil
261 }
262 // LimitCount is a non-constant expression (e.g. LIMIT $1, LIMIT (1+2)).
263 // Cannot safely rewrite in-place; let the caller fall back to CTE wrapper.
264 return "", errors.Errorf("cannot rewrite non-constant LIMIT expression")
265 }
266
267 // No LIMIT clause — find the right insertion point.
268 // PostgreSQL grammar order: ... ORDER BY ... LIMIT ... FOR UPDATE ...
269 // LIMIT goes BEFORE FOR UPDATE but AFTER everything else.
270 insertPos, beforeLocking := findLimitInsertPosition(sel)
271 if beforeLocking {
272 // Inserting at the start of FOR UPDATE/SHARE. The original whitespace
273 // before FOR becomes the separator before LIMIT; we add a trailing
274 // space to separate the limit value from FOR.
275 return sql[:insertPos] + fmt.Sprintf("LIMIT %d ", limitCount) + sql[insertPos:], nil
276 }
277 return sql[:insertPos] + fmt.Sprintf(" LIMIT %d", limitCount) + sql[insertPos:], nil
278}
279
280// findLimitInsertPosition returns the byte offset where " LIMIT N" should be inserted,
281// and whether the insertion is before a locking clause (FOR UPDATE/SHARE).

Callers 1

Calls 4

extractIntFromNodeFunction · 0.85
findLimitInsertPositionFunction · 0.85
ErrorfMethod · 0.80
nodeLocOfFunction · 0.70

Tested by

no test coverage detected