Как скомпилировать функцию определенной пользователем в SQLite

StackOverflow https://stackoverflow.com/questions/4161654

Вопрос

У меня есть пример функции C, которую я хотел бы прикрепить к базе данных temp.sqlite (Это от книги O'Reilly, поэтому я знаю, что это работает). Я прочитал раздел в книге и SQLite.org, но они придумывают, что я знаю, как и где и где компилировать эту вещь с правильными настройками. Я на i Mac (с Xcode) или Ubuntu.

Я знаю достаточно C, чтобы изменить код, чтобы сделать то, что я хочу, но я понятия не имею, что делать это из моей базы данных temp.sqlite.

Спасибо за вашу помощь! Я провалил на это!

ОБНОВЛЕНИЕ: еще несколько часов, и я сбрасывался вместе достаточно данных из заброшенных веб-страниц, чтобы создать команду компиляции и генерировать ошибку:

richard$ gcc -o wtavg wtavg.c -Wall -W -O2 -L/usr/local/lib -lsqlite3
wtavg.c: In function ‘wtavg_init’:
wtavg.c:63: warning: unused parameter ‘error’
Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

FWIW, вот wtavg.c, который прямой с сайта O'Reilly, предусмотренный в моей книге:

/* wtavg.c */

#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1;

#include <stdlib.h>




typedef struct wt_avg_state_s {
   double   total_data;  /* sum of (data * weight) values */
   double   total_wt;    /* sum of weight values */
} wt_avg_state;


static void wt_avg_step( sqlite3_context *ctx, int num_values, sqlite3_value **values )
{
    double         row_wt = 1.0;
    int            type;
    wt_avg_state   *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
                                               sizeof( wt_avg_state ) );
    if ( st == NULL ) {
        sqlite3_result_error_nomem( ctx );
        return;
    }

    /* Extract weight, if we have a weight and it looks like a number */
    if ( num_values == 2 ) {
        type = sqlite3_value_numeric_type( values[1] );
        if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
            row_wt = sqlite3_value_double( values[1] );
        }
    }

    /* Extract data, if we were given something that looks like a number. */
    type = sqlite3_value_numeric_type( values[0] );
    if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
        st->total_data += row_wt * sqlite3_value_double( values[0] );
        st->total_wt   += row_wt;
    }
}


static void wt_avg_final( sqlite3_context *ctx )
{
    double         result = 0.0;
    wt_avg_state   *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
                                               sizeof( wt_avg_state ) );
    if ( st == NULL ) {
        sqlite3_result_error_nomem( ctx );
        return;
    }

    if ( st->total_wt != 0.0 ) {
        result = st->total_data / st->total_wt;
    }
    sqlite3_result_double( ctx, result );
}


int wtavg_init( sqlite3 *db, char **error, const sqlite3_api_routines *api )
{
    SQLITE_EXTENSION_INIT2(api);

    sqlite3_create_function( db, "wtavg", 1, SQLITE_UTF8,
            NULL, NULL, wt_avg_step, wt_avg_final );
    sqlite3_create_function( db, "wtavg", 2, SQLITE_UTF8,
            NULL, NULL, wt_avg_step, wt_avg_final );

    return SQLITE_OK;
}
Это было полезно?

Решение

Функция определенной пользователем должна быть скомпилирована в виде общего файла библиотеки:

gcc -shared -fPIC -o wtavg.so wtavg.c -lsqlite3

Эта общая библиотека может быть загружена с помощью оператора SQLite:

SELECT load_extension('/path/to/wt_avg.so', 'wtavg_init');

К сожалению, версия SQLite3, предоставленной Apple, не поддерживает погрузку общих библиотек. Вместо этого вы можете использовать SQLite от MacPorts. MacPorts Программы, связывающие против SQLite, также должны иметь возможность нагрузки пользовательских функций таким образом.

При использовании SQLite внутри другой программы, однако, механизм загрузки расширения может быть отключен для соображений безопасности. В Python, например, вы должны позвонить con.enable_load_extension(True) Чтобы включить это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top