Jörgen Hägglund wrote:
> I'm trying to implement virtual tables, but I seem to be in over
> my head with this.
> I get an access violation in SQLite3.dll (reading of address 00000008)
>
> Does anyone have any ideas to what I'm doing wrong?

Not really.  But one mistake I had made was to read this paragraph:
| The xCreate method need not initialize the pModule, nRef, and zErrMsg
| fields of the sqlite3_vtab object. The SQLite core will take care of
| that chore.

... and to believe it.

> Anyone having some source of how to implement a really simple virtual
> table (in any language)?

Below, in C.


Regards,
Clemens
-- 


#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sqlite3.h>

static int test_CreateConnect(sqlite3 *db, void *pAux, int argc, const char 
*const argv[], sqlite3_vtab **ppVTab, char **pzErr)
{
        int err;

        *ppVTab = sqlite3_malloc(sizeof(struct sqlite3_vtab));
        if (!*ppVTab)
                return SQLITE_NOMEM;
        memset(*ppVTab, 0, sizeof(**ppVTab));

        err = sqlite3_declare_vtab(db, "CREATE TABLE x(ID INTEGER, Name TEXT)");
        if (err != SQLITE_OK) {
                sqlite3_free(*ppVTab);
                *ppVTab = NULL;
                return err;
        }

        return SQLITE_OK;
}

static int test_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *index_info)
{
        index_info->idxNum = 0;
        index_info->idxStr = "";
        index_info->estimatedCost = 1000000;
        return SQLITE_OK;
}

static int test_DisconnectDestroy(sqlite3_vtab *pVTab)
{
        sqlite3_free(pVTab);
        return SQLITE_OK;
}

struct test_cursor {
        sqlite3_vtab_cursor base;
        int row;
};

static int test_Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
{
        struct test_cursor *cursor;

        cursor = sqlite3_malloc(sizeof(struct test_cursor));
        if (!cursor)
                return SQLITE_NOMEM;
        memset(cursor, 0, sizeof(*cursor));

        *ppCursor = &cursor->base;

        return SQLITE_OK;
}

static int test_Close(sqlite3_vtab_cursor *pCursor)
{
        sqlite3_free(pCursor);
        return SQLITE_OK;
}

static int test_Eof(sqlite3_vtab_cursor *pCursor)
{
        struct test_cursor *cursor = (void *)pCursor;

        return cursor->row >= 5;
}

static int test_Filter(sqlite3_vtab_cursor *pCursor, int idxNum, const char 
*idxStr, int argc, sqlite3_value **argv)
{
        struct test_cursor *cursor = (void *)pCursor;

        cursor->row = 0;
        return SQLITE_OK;
}

static int test_Next(sqlite3_vtab_cursor *pCursor)
{
        struct test_cursor *cursor = (void *)pCursor;

        cursor->row++;
        return SQLITE_OK;
}

static int test_Column(sqlite3_vtab_cursor *pCursor, sqlite3_context *context, 
int N)
{
        struct test_cursor *cursor = (void *)pCursor;
        char str[16];

        switch (N) {
        case 0:
                sqlite3_result_int(context, 42 + cursor->row);
                break;
        case 1:
                sprintf(str, "row%d", cursor->row);
                sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
                break;
        }
        return SQLITE_OK;
}

static int test_Rowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid)
{
        struct test_cursor *cursor = (void *)pCursor;

        *pRowid = cursor->row;
        return SQLITE_OK;
}

static int test_Rename(sqlite3_vtab* pVTab, const char *zNew)
{
        return SQLITE_OK;
}

static sqlite3_module module = {
        .iVersion = 1,
        .xCreate = test_CreateConnect,
        .xConnect = test_CreateConnect,
        .xBestIndex = test_BestIndex,
        .xDisconnect = test_DisconnectDestroy,
        .xDestroy = test_DisconnectDestroy,
        .xOpen = test_Open,
        .xClose = test_Close,
        .xFilter = test_Filter,
        .xNext = test_Next,
        .xEof = test_Eof,
        .xColumn = test_Column,
        .xRowid = test_Rowid,
        .xRename = test_Rename,
};

int main(int argc, char *argv[])
{
        sqlite3 *db;
        sqlite3_stmt *stmt;
        int res, cols, i;

        res = sqlite3_open(":memory:", &db);
        assert(res == SQLITE_OK);

        res = sqlite3_create_module(db, "test", &module, NULL);
        assert(res == SQLITE_OK);

        res = sqlite3_exec(db, "create virtual table t1 using test", NULL, 
NULL, NULL);
        assert(res == SQLITE_OK);

        res = sqlite3_prepare_v2(db, "select * from t1", -1, &stmt, NULL);
        assert(res == SQLITE_OK);
        cols = sqlite3_column_count(stmt);
        res = sqlite3_step(stmt);
        while (res == SQLITE_ROW) {
                for (i = 0; i < cols; i++)
                        printf(" %s", sqlite3_column_text(stmt, i));
                putchar('\n');
                res = sqlite3_step(stmt);
        }
        assert(res == SQLITE_DONE);
        sqlite3_finalize(stmt);

        sqlite3_close(db);

        return 0;
}
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to