@@ -193,9 +193,12 @@ final class QueryViewModel {
193193 let toIndex = columnOrder.firstIndex(of: targetColumn),
194194 fromIndex != toIndex else { return }
195195 let item = columnOrder.remove(at: fromIndex)
196− // Removing an element before the target shifts the target down by one, so
197− // inserting at the original `toIndex` would land the column past its target.
198− let adjusted = fromIndex < toIndex ? toIndex - 1 : toIndex
196+ // Match the drop-indicator semantics: a rightward move (fromIndex < toIndex)
197+ // lands the column *after* the target, a leftward move lands it *before*.
198+ // After removing an earlier element the target shifts down by one, so
199+ // inserting at `toIndex` lands after the target for rightward moves; for
200+ // leftward moves the target is unshifted and `toIndex` lands before it.
201+ let adjusted = toIndex
199202 columnOrder.insert(item, at: adjusted)
200203 saveColumnConfig()
201204 updateSQLColumns()
@@ -627,6 +630,9 @@ final class QueryViewModel {
627630 var depth = 0
628631 var whereEnd: String.Index?
629632 var tailStart: String.Index?
633+ // Track whether the existing WHERE body has a top-level OR — only then does
634+ // AND-ing a new condition need parentheses to preserve precedence.
635+ var bodyHasTopLevelOr = false
630636 for token in SQLTokenizer.tokenize(sql) {
631637 switch token.kind {
632638 case .leftParen:
@@ -638,6 +644,8 @@ final class QueryViewModel {
638644 whereEnd = token.range.upperBound
639645 } else if tailKeywords.contains(kw), tailStart == nil {
640646 tailStart = token.range.lowerBound
647+ } else if kw == "OR", whereEnd != nil, tailStart == nil {
648+ bodyHasTopLevelOr = true
641649 }
642650 default:
643651 break
@@ -646,16 +654,18 @@ final class QueryViewModel {
646654
647655 if let whereEnd {
648656 // Parenthesize the existing WHERE body before AND-ing the new
649− // condition, otherwise an existing top-level OR silently changes
650− // meaning: `WHERE a = 1 OR b = 2` would become
657+ // condition only when it has a top-level OR, otherwise the OR
658+ // silently changes meaning: `WHERE a = 1 OR b = 2` would become
651659 // `WHERE a = 1 OR b = 2 AND c = 3`, which SQL binds as
652660 // `a = 1 OR (b = 2 AND c = 3)` rather than the intended
653− // `(a = 1 OR b = 2) AND c = 3`.
661+ // `(a = 1 OR b = 2) AND c = 3`. A body without a top-level OR is
662+ // left un-parenthesized so simple filters stay readable.
654663 let bodyEnd = tailStart ?? sql.endIndex
655664 let head = sql[..<whereEnd]
656665 let body = sql[whereEnd..<bodyEnd].trimmingCharacters(in: .whitespacesAndNewlines)
657666 let tail = sql[bodyEnd...].trimmingCharacters(in: .whitespacesAndNewlines)
658− sql = "\(head) (\(body)) AND \(condition)"
667+ let wrappedBody = bodyHasTopLevelOr ? "(\(body))" : body
668+ sql = "\(head) \(wrappedBody) AND \(condition)"
659669 if !tail.isEmpty {
660670 sql += " \(tail)"
661671 }