Параметры привязки SQLite напрямую по имени

Недавно я совсем недавно начал изучать, как программировать для 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 не сильно типизированы, и я технически мог это сделать в любом случае), б) он чувствовал себя нелепым взломом, и в) я предположил, что существует причина, по которой этот подход широко не использовался. Итак:

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

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

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

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

Ответ 1

  • Есть; это функция sqlite3_bind_parameter_index(), о которой вы говорили, что вы используете, чтобы превратить имя параметра в индекс, который затем можно использовать с sqlite3_bind_*(). Однако нет функции sqlite3_bind_*_by_name() или чего-либо подобного. Это поможет предотвратить раздувание API. В популярной оболочке sqlite базы данных Flying Meat есть поддержка именованных параметров в одном из ее ветвей, если вам интересно посмотреть, как она используется.

    Если вы думаете о том, что потребуется для реализации полных именованных методов привязки параметров, рассмотрим текущий список функций 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?), Им нужно добавить только одну функцию, а не две.

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