В отличие от ответа @ Shawn, оказывается, что реализация пользовательской функции SQL на самом деле довольно проста:
/* Implement the DATALENGTH() SQL function. Code adapted from the SQLite source
* for the LENGTH() function.
*/
static void db_sqlite_datalength(sqlite3_context *context, int argc,
sqlite3_value **argv)
{
(void) argc;
switch(sqlite3_value_type(argv[0])) {
case SQLITE_BLOB:
case SQLITE_INTEGER:
case SQLITE_FLOAT:
case SQLITE_TEXT:
sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
break;
default:
sqlite3_result_null(context);
break;
}
}
static int db_register_custom_functions(sqlite3 *db)
{
return sqlite3_create_function(db, "datalength", 1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
&db_sqlite_datalength, NULL, NULL);
}
Поскольку встроенная функция length
реализована точно так же, производительность должно быть в порядке. Я немного просмотрел исходники sqlite3, но не так просто определить, когда именно происходит доступ к диску. Предположительно, sqlite3 mmap
имеет все, что важно для производительности, - это то, что возможные переполнения страниц для длинных полей TEXT
не требуются без необходимости.