Правильная привязка параметров для SELECT WHERE .. LIKE с использованием fmdb?

Первый раз пользователь fmdb здесь, пытаясь начать делать все правильно. У меня есть простая единственная таблица, которую я хочу выполнить с помощью запроса SELECT WHERE .. LIKE, и после того, как я попробовал несколько задокументированных подходов, я не могу получить ни одного, чтобы получить правильные результаты.

e.g.

// 'filter' is an NSString * containing a fragment of
//  text that we want in the 'track' column
NSDictionary *params =
  [NSDictionary dictionaryWithObjectsAndKeys:filter, @"filter", nil];

FMResultSet *results =
  [db executeQuery:@"SELECT * FROM items WHERE track LIKE '%:filter%' ORDER BY linkNum;"
      withParameterDictionary:params];

Or

results = [db executeQuery:@"SELECT * FROM items WHERE track LIKE '%?%' ORDER BY linkNum;", filter];

Or

results = [db executeQuery:@"SELECT * FROM items WHERE track LIKE '%?%' ORDER BY linkNum;" withArgumentsInArray:@[filter]];

Я прошел, и все методы сходятся в методе fmdb:

- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args

В зависимости от подхода и, следовательно, от того, какие параметры равны нулю, он либо вызывает sqlite3_bind_parameter_count(pStmt), который всегда возвращает ноль, либо, в случае со словарем, вызывает sqlite3_bind_parameter_index(..), который также возвращает ноль, поэтому параметр не попадает в LIKE и то набор результатов из запроса неверен.

Я знаю, что это абсолютно неправильный способ сделать это (SQL-инъекция), но это единственный способ, которым мне удалось выполнить мой LIKE:

NSString *queryString = [NSString stringWithFormat:@"SELECT * FROM items WHERE track LIKE '%%%@%%' ORDER BY linkNum;", filter];
results = [db executeQuery:queryString];

(Я также пробовал все перестановки, но с экранированными двойными кавычками вместо одинарных кавычек, показанных здесь)

Обновление:

Я также пробовал собственный вариант fmdb …WithFormat, который должен обеспечить удобство и защиту от внедрения:

[db executeQueryWithFormat:@"SELECT * FROM items WHERE track LIKE '%%%@%%' ORDER BY linkNum;", filter];

Опять же, войдя в отладчик, я вижу, что LIKE преобразуется из этого:

… LIKE '%%%@%%' ORDER BY linkNum;

К этому:

… LIKE '%%?%' ORDER BY linkNum;

… который также возвращает ноль из sqlite3_bind_parameter_count(), где я ожидаю положительное значение, равное «индексу самого большого (самого правого) параметра». (из документов sqlite)


person Chris    schedule 20.03.2014    source источник


Ответы (1)


Ошибка заключалась в том, чтобы вообще включать какие-либо кавычки:

[db executeQuery:@"SELECT * FROM items WHERE track LIKE ? ORDER BY linkNum;", filter]; 

… и % теперь находится в переменной filter, а не в запросе.

person Chris    schedule 20.03.2014
comment
Чтобы это сработало, я предполагаю, что вы включили % в значение filter. - person Rob; 18.05.2014