代码之家  ›  专栏  ›  技术社区  ›  Richard Herron

如何在SQLite中编译用户定义函数

  •  0
  • Richard Herron  · 技术社区  · 15 年前

    temp.sqlite (这是一本奥雷利的书,所以我知道它有效)。我在书和sqlite.org上读过这一节,但他们认为我知道如何以及在何处用正确的设置编译这个东西。我在Mac(带XCode)或Ubuntu上。

    我知道足够多的C来修改代码来做我想做的事情,但是我不知道该怎么做,从我的数据库中调用它 温度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
    

    /* 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;
    }
    
    1 回复  |  直到 15 年前
        1
  •  3
  •   Alex Jasmin    15 年前

    用户定义的函数应编译为共享库文件:

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

    然后可以使用SQLite语句加载该共享库:

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

    但是,当在另一个程序中使用SQLite时,出于安全原因,可能会禁用扩展加载机制。例如在Python中,您必须调用 con.enable_load_extension(True) 使能。

    推荐文章