Как правильно заменить местозаполнители в запросе?
Логика скрипта состоит в том, чтобы в метод передавался запрос (query) и неограниченный кортеж values.
После, метод перебирает кортеж values (сохраняет в переменную), находит все индексы символа ? и вставляет значения кортежа values в список под индексом символа '?'.
Вот код, но он заменяет лишь почему-то на последнее значение:
def test(query, *values):
print(f"Query: {query}\nValues: {values}")
query_list = list(query)
indexes = {}
for count, value in enumerate(query_list):
if value == '?':
print(f"\n[*] Знак '?' найден в списке под индексом {count}")
for i in range(len(values)):
print(f"Index of value: [{i}], Index of symbol: {count}")
indexes[count] = values[i]
for key, value in indexes.items():
query_list[key] = value
query = "".join(query_list)
print(f"Result: {query}\nDict: {indexes}")
Вывод:
Query: SELECT * FROM `?` WHERE `password` = ? AND `login` = ?
Values: ('users', 'qwerty', 'Alex2007')
[*] Знак '?' найден в списке под индексом 15
Index of value: [0], Index of symbol: 15
Index of value: [1], Index of symbol: 15
Index of value: [2], Index of symbol: 15
[*] Знак '?' найден в списке под индексом 37
Index of value: [0], Index of symbol: 37
Index of value: [1], Index of symbol: 37
Index of value: [2], Index of symbol: 37
[*] Знак '?' найден в списке под индексом 53
Index of value: [0], Index of symbol: 53
Index of value: [1], Index of symbol: 53
Index of value: [2], Index of symbol: 53
Result: SELECT * FROM `Alex2007` WHERE `password` = Alex2007 AND `login` = Alex2007
Dict: {15: 'Alex2007', 37: 'Alex2007', 53: 'Alex2007'}
Ответы (2 шт):
попробуйте изменить код так:
values = iter(values)
for count, value in enumerate(query_list):
if value == '?':
print(f"\n[*] Знак '?' найден в списке под индексом {count}")
v = next(values)
print(f"Value: [{v}], Index of symbol: {count}")
indexes[count] = v
У вас неправильный и опасный подход. Таким образом вы открываетесь для SQL Injections.
Правильным подходом здесь будет использование связываемых переменных (синонимы: prepared statement, bind variables). Связать можно только литералы, но не наименования таблиц или столбцов. Поэтому вашу задачу придется разделить на две части - динамическое формирование запроса с подставлением названий таблиц / столбцов и на безопасное связывание переменных:
qry_template = """SELECT * FROM {} WHERE password = ? AND login = ?"""
пользоваться этим нужно так:
cursor.execute(qry_template.format(table_name), values) # здесь значения переменных `password` и `login` автоматически свяжутся со значениями из списка или кортежа `values`
for row in cursor.fetchall():
...
можно также использовать f-string, но интерполяция переменной будет происходить в момент создания / объявления переменной qry:
table_name = "my_table_name"
qry = f"""SELECT * FROM {table_name} WHERE password = ? AND login = ?"""
....
cursor.execute(qry, values)