@@ -200,7 +200,6 @@ final class QueryHistoryStorage {
200200
201201 var statement : OpaquePointer ?
202202 guard sqlite3_prepare_v2 ( self . db, sql, - 1 , & statement, nil ) == SQLITE_OK else {
203- print ( " [QueryHistory] Failed to prepare INSERT statement " )
204203 DispatchQueue . main. async { completion ? ( false ) }
205204 return
206205 }
@@ -228,12 +227,7 @@ final class QueryHistoryStorage {
228227 let result = sqlite3_step ( statement)
229228 let success = result == SQLITE_DONE
230229
231- if !success {
232- let errorMsg = String ( cString: sqlite3_errmsg ( self . db) )
233- print ( " [QueryHistory] INSERT failed: \( errorMsg) " )
234- } else {
235- print ( " [QueryHistory] Successfully recorded query " )
236- }
230+ // Silently handle errors - logging can be added via proper logging framework if needed
237231
238232 DispatchQueue . main. async { completion ? ( success) }
239233 }
@@ -250,37 +244,52 @@ final class QueryHistoryStorage {
250244 return queue. sync {
251245 var entries : [ QueryHistoryEntry ] = [ ]
252246
253- // Build query
254- var sql = " SELECT id, query, connection_id, database_name, executed_at, execution_time, row_count, was_successful, error_message FROM history "
255- var whereClauses : [ String ] = [ ]
256-
257- if let connectionId = connectionId {
258- whereClauses. append ( " connection_id = ' \( connectionId. uuidString) ' " )
259- }
260-
261- if let startDate = dateFilter. startDate {
262- whereClauses. append ( " executed_at >= \( startDate. timeIntervalSince1970) " )
263- }
247+ // Build query with placeholders
248+ var sql : String
249+ var bindIndex : Int32 = 1
250+ var hasConnectionFilter = false
251+ var hasDateFilter = false
264252
265253 // Use FTS5 for full-text search if search text provided
266254 if let searchText = searchText, !searchText. isEmpty {
267- let ftsQuery = searchText. replacingOccurrences ( of: " ' " , with: " '' " )
268255 sql = """
269256 SELECT h.id, h.query, h.connection_id, h.database_name, h.executed_at, h.execution_time, h.row_count, h.was_successful, h.error_message
270257 FROM history h
271258 INNER JOIN history_fts ON h.rowid = history_fts.rowid
272- WHERE history_fts MATCH ' \( ftsQuery ) '
259+ WHERE history_fts MATCH ?
273260 """
274261
275- // Add other where clauses if needed
262+ // Add additional filters
263+ if connectionId != nil {
264+ sql += " AND h.connection_id = ? "
265+ hasConnectionFilter = true
266+ }
267+
268+ if dateFilter. startDate != nil {
269+ sql += " AND h.executed_at >= ? "
270+ hasDateFilter = true
271+ }
272+ } else {
273+ sql = " SELECT id, query, connection_id, database_name, executed_at, execution_time, row_count, was_successful, error_message FROM history "
274+
275+ var whereClauses : [ String ] = [ ]
276+
277+ if connectionId != nil {
278+ whereClauses. append ( " connection_id = ? " )
279+ hasConnectionFilter = true
280+ }
281+
282+ if dateFilter. startDate != nil {
283+ whereClauses. append ( " executed_at >= ? " )
284+ hasDateFilter = true
285+ }
286+
276287 if !whereClauses. isEmpty {
277- sql += " AND " + whereClauses. joined ( separator: " AND " )
288+ sql += " WHERE " + whereClauses. joined ( separator: " AND " )
278289 }
279- } else if !whereClauses. isEmpty {
280- sql += " WHERE " + whereClauses. joined ( separator: " AND " )
281290 }
282291
283- sql += " ORDER BY executed_at DESC LIMIT \( limit ) OFFSET \( offset ) ; "
292+ sql += " ORDER BY executed_at DESC LIMIT ? OFFSET ? ; "
284293
285294 var statement : OpaquePointer ?
286295 guard sqlite3_prepare_v2 ( db, sql, - 1 , & statement, nil ) == SQLITE_OK else {
@@ -289,6 +298,28 @@ final class QueryHistoryStorage {
289298
290299 defer { sqlite3_finalize ( statement) }
291300
301+ let SQLITE_TRANSIENT = unsafeBitCast ( - 1 , to: sqlite3_destructor_type. self)
302+
303+ // Bind parameters in order
304+ if let searchText = searchText, !searchText. isEmpty {
305+ sqlite3_bind_text ( statement, bindIndex, searchText, - 1 , SQLITE_TRANSIENT)
306+ bindIndex += 1
307+ }
308+
309+ if let connectionId = connectionId, hasConnectionFilter {
310+ sqlite3_bind_text ( statement, bindIndex, connectionId. uuidString, - 1 , SQLITE_TRANSIENT)
311+ bindIndex += 1
312+ }
313+
314+ if let startDate = dateFilter. startDate, hasDateFilter {
315+ sqlite3_bind_double ( statement, bindIndex, startDate. timeIntervalSince1970)
316+ bindIndex += 1
317+ }
318+
319+ sqlite3_bind_int ( statement, bindIndex, Int32 ( limit) )
320+ bindIndex += 1
321+ sqlite3_bind_int ( statement, bindIndex, Int32 ( offset) )
322+
292323 while sqlite3_step ( statement) == SQLITE_ROW {
293324 if let entry = parseHistoryEntry ( from: statement) {
294325 entries. append ( entry)
@@ -358,8 +389,6 @@ final class QueryHistoryStorage {
358389
359390 var statement : OpaquePointer ?
360391 guard sqlite3_prepare_v2 ( db, sql, - 1 , & statement, nil ) == SQLITE_OK else {
361- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
362- print ( " [QueryHistoryStorage] Failed to prepare bookmark INSERT: \( errorMsg) " )
363392 return false
364393 }
365394
@@ -401,12 +430,7 @@ final class QueryHistoryStorage {
401430 let result = sqlite3_step ( statement)
402431 let success = result == SQLITE_DONE
403432
404- if !success {
405- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
406- print ( " [QueryHistoryStorage] Bookmark INSERT failed: \( errorMsg) " )
407- } else {
408- print ( " [QueryHistoryStorage] Successfully saved bookmark: \( nameString) " )
409- }
433+ // Silently handle errors
410434
411435 return success
412436 }
@@ -432,8 +456,6 @@ final class QueryHistoryStorage {
432456
433457 var statement : OpaquePointer ?
434458 guard sqlite3_prepare_v2 ( db, sql, - 1 , & statement, nil ) == SQLITE_OK else {
435- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
436- print ( " [QueryHistoryStorage] Failed to prepare bookmark UPDATE: \( errorMsg) " )
437459 return false
438460 }
439461
@@ -474,12 +496,7 @@ final class QueryHistoryStorage {
474496 let result = sqlite3_step ( statement)
475497 let success = result == SQLITE_DONE
476498
477- if !success {
478- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
479- print ( " [QueryHistoryStorage] Bookmark UPDATE failed: \( errorMsg) " )
480- } else {
481- print ( " [QueryHistoryStorage] Successfully updated bookmark: \( nameString) " )
482- }
499+ // Silently handle errors
483500
484501 return success
485502 }
@@ -492,15 +509,18 @@ final class QueryHistoryStorage {
492509
493510 var sql = " SELECT id, name, query, connection_id, tags, created_at, last_used_at, notes FROM bookmarks "
494511 var whereClauses : [ String ] = [ ]
512+ var bindIndex : Int32 = 1
513+ var hasSearchFilter = false
514+ var hasTagFilter = false
495515
496516 if let searchText = searchText, !searchText. isEmpty {
497- let escaped = searchText . replacingOccurrences ( of : " ' " , with : " '' " )
498- whereClauses . append ( " (name LIKE '% \( escaped ) %' OR query LIKE '% \( escaped ) %') " )
517+ whereClauses . append ( " (name LIKE ? OR query LIKE ?) " )
518+ hasSearchFilter = true
499519 }
500520
501521 if let tag = tag, !tag. isEmpty {
502- let escaped = tag . replacingOccurrences ( of : " ' " , with : " '' " )
503- whereClauses . append ( " tags LIKE '% \( escaped ) %' " )
522+ whereClauses . append ( " tags LIKE ? " )
523+ hasTagFilter = true
504524 }
505525
506526 if !whereClauses. isEmpty {
@@ -516,6 +536,22 @@ final class QueryHistoryStorage {
516536
517537 defer { sqlite3_finalize ( statement) }
518538
539+ let SQLITE_TRANSIENT = unsafeBitCast ( - 1 , to: sqlite3_destructor_type. self)
540+
541+ // Bind parameters in order
542+ if let searchText = searchText, !searchText. isEmpty, hasSearchFilter {
543+ let searchPattern = " % \( searchText) % "
544+ sqlite3_bind_text ( statement, bindIndex, searchPattern, - 1 , SQLITE_TRANSIENT)
545+ bindIndex += 1
546+ sqlite3_bind_text ( statement, bindIndex, searchPattern, - 1 , SQLITE_TRANSIENT)
547+ bindIndex += 1
548+ }
549+
550+ if let tag = tag, !tag. isEmpty, hasTagFilter {
551+ let tagPattern = " % \( tag) % "
552+ sqlite3_bind_text ( statement, bindIndex, tagPattern, - 1 , SQLITE_TRANSIENT)
553+ }
554+
519555 while sqlite3_step ( statement) == SQLITE_ROW {
520556 if let bookmark = parseBookmark ( from: statement) {
521557 bookmarks. append ( bookmark)
@@ -534,8 +570,6 @@ final class QueryHistoryStorage {
534570 let sql = " DELETE FROM bookmarks WHERE id = ?; "
535571 var statement : OpaquePointer ?
536572 guard sqlite3_prepare_v2 ( db, sql, - 1 , & statement, nil ) == SQLITE_OK else {
537- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
538- print ( " [QueryHistoryStorage] Failed to prepare DELETE bookmark: \( errorMsg) " )
539573 return false
540574 }
541575
@@ -547,16 +581,7 @@ final class QueryHistoryStorage {
547581 let result = sqlite3_step ( statement)
548582 let success = result == SQLITE_DONE
549583
550- if success {
551- let changes = sqlite3_changes ( db)
552- print ( " [QueryHistoryStorage] Deleted bookmark \( idString) , rows affected: \( changes) " )
553- if changes == 0 {
554- print ( " [QueryHistoryStorage] WARNING: Delete succeeded but no rows were affected! " )
555- }
556- } else {
557- let errorMsg = String ( cString: sqlite3_errmsg ( db) )
558- print ( " [QueryHistoryStorage] Failed to DELETE bookmark: \( errorMsg) , result: \( result) " )
559- }
584+ // Silently handle success/failure
560585
561586 return success
562587 }
0 commit comments