Связывание параметров SQLite напрямую по имени - PullRequest
10 голосов
/ 22 сентября 2011

Я недавно - совсем недавно - начал изучать программирование для iOS, и был озадачен тем, что кажется (на мой взгляд) явным упущением в SQLite3.Позвольте мне уточнить это, сказав, что до прошлой недели у меня был нулевой (практический) опыт работы с Mac, Objective C, Xcode, iOS или SQLite, поэтому у меня нет никаких заблуждений о том, чтобы вникать в область проверенных инструментов и находить очевидные ошибки.с моей первой попытки.Я предполагаю, что есть хорошее объяснение.

Однако, проведя последние несколько месяцев с использованием SQL Server, MySQL и PostgreSQL, я был поражен, обнаружив, что SQLite не имеет лучшей функциональности для добавления параметров по имени.Все, что я мог найти в Интернете (документация, форумы [включая SO]), говорит о назначении параметров, используя их целочисленный индекс, что, похоже, будет сложно поддерживать, если вы когда-нибудь измените свои запросы.Даже если вы можете назвать параметры в ваших утверждениях и делать что-то вроде

sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@my_param"), myInt);

, похоже, никто этого не делает.На самом деле, кажется, никто не пытается автоматизировать это вообще;единственный альтернативный подход , который я мог найти, использовал массив параметров и счетчик циклов и проверял каждый параметр, чтобы определить, какой тип объекта вставлять.Первоначально я рассматривал подобный подход, но а) позиция моего босса заключается в том, что параметры базы данных всегда должны проверяться на тип (и я согласен, хотя я понимаю, что поля SQLite не являются строго типизированными, и я технически мог бы сделать это в любом случае), б) эточувствовал себя неумелым взломом, и c) я предположил, что была причина, по которой этот подход не получил широкого распространения.Итак:

1) Почему в SQLite отсутствуют методы привязки, которые принимают имя параметра (например, «const char»)?Или я что-то упустил?

2) Почему никто не использует подход, подобный приведенному выше?

Я немного покопался в исходном коде и думаю, что мог бы легко модифицировать библиотеку или просто написать свои собственные (типизированные) методы класса, которые бы делали для меня вышеупомянутое, но я предполагаю, что нет ни одной причинывстроил это в SQLite еще.Я могу только предположить, что дополнительная память и циклы, необходимые для поиска индекса параметра, слишком ценны для [вставьте здесь iDevice] и не стоят удобства использования имен параметров.,,?

Любое понимание будет оценено.

1 Ответ

4 голосов
/ 22 сентября 2011
  1. Есть; Вы упомянули функцию sqlite3_bind_parameter_index(), которую вы используете для преобразования имени параметра в индекс, который затем можно использовать с функциями sqlite3_bind_*(). Тем не менее, нет функции sqlite3_bind_*_by_name() или чего-то подобного. Это поможет предотвратить раздувание API. Популярная оболочка sqlite для базы данных Flying Meat Database поддерживает именованные параметры в одной из своих ветвей, если вам интересно узнать, как она используется.

    Если вы думаете о том, что потребуется для реализации полных методов привязки именованных параметров, рассмотрите текущий список bind функций:

    int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
    int sqlite3_bind_double(sqlite3_stmt*, int, double);
    int sqlite3_bind_int(sqlite3_stmt*, int, int);
    int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
    int sqlite3_bind_null(sqlite3_stmt*, int);
    int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
    int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
    int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
    int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
    

    Если бы мы хотели добавить явную поддержку именованных параметров, этот список удвоился бы по длине, чтобы включить:

    int sqlite3_bind_name_blob(sqlite3_stmt*, const char*, const void*, int n, void(*)(void*));
    int sqlite3_bind_name_double(sqlite3_stmt*, const char*, double);
    int sqlite3_bind_name_int(sqlite3_stmt*, const char*, int);
    int sqlite3_bind_name_int64(sqlite3_stmt*, const char*, sqlite3_int64);
    int sqlite3_bind_name_null(sqlite3_stmt*, const char*);
    int sqlite3_bind_name_text(sqlite3_stmt*, const char*, const char*, int n, void(*)(void*));
    int sqlite3_bind_name_text16(sqlite3_stmt*, const char*, const void*, int, void(*)(void*));
    int sqlite3_bind_name_value(sqlite3_stmt*, const char*, const sqlite3_value*);
    int sqlite3_bind_name_zeroblob(sqlite3_stmt*, const char*, int n);
    

    В два раза больше функций означает гораздо больше времени, затрачиваемого на поддержку API, обеспечение обратной совместимости и т. Д. И т. Д. Однако, просто введя sqlite3_bind_parameter_index(), они смогли добавить полную поддержку именованных параметров только с одиночная функция. Это означает, что если они когда-нибудь решат поддерживать новые типы связывания (возможно, sqlite3_bind_int128?), Им нужно будет добавить только одну функцию, а не две.

  2. Что касается того, почему никто, кажется, не использует его ... Я не могу дать какого-либо однозначного ответа при проведении опроса. Мое предположение было бы более естественным для последовательной ссылки на параметры, и в этом случае именованные параметры не так полезны. Именованные параметры кажутся полезными, только если вам нужно обращаться к параметрам не по порядку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...