コード例 #1
0
ファイル: flexi_data_vtable.c プロジェクト: slanska/flexilite
/*
 * Returns value for the column at position iCol (starting from 0).
 * Reads column data from ref-values table, filtered by ObjectID and sorted by PropertyID
 * For the sake of better performance, fetches required columns on demand, sequentially.
 *
 */
static int _column(sqlite3_vtab_cursor *pCursor, sqlite3_context *pContext, int iCol)
{
    int result = SQLITE_OK;
    struct flexi_VTabCursor *cur = (void *) pCursor;

    if (iCol == -1)
    {
        sqlite3_result_int64(pContext, cur->lObjectID);
        goto EXIT;
    }

    struct flexi_ClassDef_t *vtab = (void *) cur->base.pVtab;

    // First, check if column has been already loaded
    while (cur->iReadCol < iCol)
    {
        int colResult = sqlite3_step(cur->pPropertyIterator);
        if (colResult == SQLITE_DONE)
            break;
        if (colResult != SQLITE_ROW)
        {
            result = colResult;
            goto ONERROR;
        }
        sqlite3_int64 lPropID = sqlite3_column_int64(cur->pPropertyIterator, 1);
        if (lPropID < vtab->pProps[cur->iReadCol + 1].iPropID)
            continue;

        cur->iReadCol++;
        if (lPropID == vtab->pProps[cur->iReadCol].iPropID)
        {
            sqlite3_int64 lPropIdx = sqlite3_column_int64(cur->pPropertyIterator, 2);

            /*
             * No need in any special verification as we expect columns are sorted by property IDs, so
             * we just assume that once column index is OK, we can process this property data
             */

            cur->pCols[cur->iReadCol] = sqlite3_value_dup(sqlite3_column_value(cur->pPropertyIterator, 4));
        }
    }

    if (cur->pCols[iCol] == NULL || sqlite3_value_type(cur->pCols[iCol]) == SQLITE_NULL)
    {
        sqlite3_result_value(pContext, vtab->pProps[iCol].defaultValue);
    }
    else
    {
        sqlite3_result_value(pContext, cur->pCols[iCol]);
    }

    result = SQLITE_OK;
    goto EXIT;
    ONERROR:

    EXIT:
    // Map column number to property ID
    return result;
}
コード例 #2
0
ファイル: sql_test_runner.c プロジェクト: slanska/flexilite
/*
 * Executes SQL statement zSql on zDatabase, using parameters zArgs and file name substitutions zFileArgs
 * Result data is loaded onto pData, and pRowCnt and pColCnt will indicate number of loaded rows and
 * number of columns in the row. Total number of items in pData will be nRowCnt * nColCnt
 */
static int
_runSql(char *zDatabase, char *zSrcSql, char *zArgs, char *zFileArgs, Array_t *pData, int *pColCnt,
        char *zEntryFilePath,
        char *zSubstFileNames)
{
    int result;

    sqlite3 *pDB = NULL;
    sqlite3_stmt *pStmt = NULL;
    sqlite3_stmt *pArgsStmt = NULL;
    Array_t sqlArgs;
    char *zError = NULL;
    char *zFullFilePath = NULL;
    sqlite3_stmt *pSubstStmt = NULL;
    char *zFileContent = NULL;
    char *zSchemaSql = NULL;

    char *zSql = strCopy(zSrcSql, -1);

    /*
    * Only first 16 substitute parameters will be processed. This is related to the fact that in C there
    * is no non-hacking way to dynamically build variadic arguments. So, to support list of values we just
    * limit maximum number of substitute strings to reasonably high number (16)
    */
    const char *zz[16];
    memset(&zz, 0, sizeof(zz));

    Array_init(&sqlArgs, sizeof(SqlArg_t), (void *) _freeSqlArg);

    *pColCnt = 0;

    //    Array_init(pData, sizeof(sqlite3_value *), (void *) _freeSqliteValue);

    /*
    * Open database (use :memory: if not defined)
    */
    if (zDatabase == NULL || strlen(zDatabase) == 0)
    {
        zDatabase = ":memory:";
    }
    CHECK_CALL(sqlite3_open_v2(zDatabase, &pDB,
                               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE,
                               NULL));

    CHECK_CALL(sqlite3_enable_load_extension(pDB, 1));

    // load extension library
    CHECK_CALL(sqlite3_load_extension(pDB, "../../bin/libFlexilite", NULL, &zError));

    // load and run db schema
    CHECK_CALL(file_load_utf8("../../sql/dbschema.sql", &zSchemaSql));
    CHECK_CALL(sqlite3_exec(pDB, (const char *) zSchemaSql, NULL, NULL, &zError));

    /*
     * Substitute strings
     */
    if (!STR_EMPTY(zSubstFileNames))
    {
        CHECK_STMT_PREPARE(pDB, "select key, value from json_each(:1);", &pSubstStmt);
        CHECK_CALL(sqlite3_bind_text(pSubstStmt, 1, zSubstFileNames, -1, NULL));
        int nSubst = 0;
        while ((result = sqlite3_step(pSubstStmt)) == SQLITE_ROW)
        {
            if (nSubst >= 16)
            {
                result = SQLITE_ERROR;
                zError = "Number of substitute strings must not exceed 16";
                goto ONERROR;
            }
            sqlite3_free(zFullFilePath);
            zFullFilePath = NULL;

            Path_join(&zFullFilePath, zEntryFilePath, (char *) sqlite3_column_text(pSubstStmt, 1));

            CHECK_CALL(file_load_utf8(zFullFilePath, &zFileContent));

            zz[nSubst++] = zFileContent;
            zFileContent = NULL; // Memory will be freed by zz
        }
        if (result != SQLITE_DONE)
            goto ONERROR;

        char *zTemp = zSql;
        zSql = sqlite3_mprintf(zTemp, zz[0], zz[1], zz[2], zz[3], zz[4], zz[5], zz[6], zz[7], zz[8],
                               zz[9], zz[10], zz[11], zz[12], zz[13], zz[14], zz[15]);
        sqlite3_free(zTemp);
    }

    // TODO use flexi('init')

    CHECK_STMT_PREPARE(pDB, zSql, &pStmt);

    // Check if we have arguments JSON. Prepare arguments
    if (!STR_EMPTY(zArgs))
    {
        CHECK_STMT_PREPARE(pDB, "select value, type from json_each(:1);", &pArgsStmt);
        CHECK_CALL(sqlite3_bind_text(pArgsStmt, 1, zArgs, -1, NULL));
        int nArgCnt = 0;
        while ((result = sqlite3_step(pArgsStmt)) == SQLITE_ROW)
        {
            SqlArg_t item;
            memset(&item, 0, sizeof(item));
            item.pValue = sqlite3_value_dup(sqlite3_column_value(pArgsStmt, 0));
            Array_setNth(&sqlArgs, sqlArgs.iCnt, &item);
            nArgCnt++;
        }

        if (result != SQLITE_DONE)
            goto ONERROR;

        /*
         * Process file args
         */
        CHECK_CALL(sqlite3_reset(pArgsStmt));
        CHECK_CALL(sqlite3_bind_text(pArgsStmt, 1, zFileArgs, -1, NULL));
        while ((result = sqlite3_step(pArgsStmt)) == SQLITE_ROW)
        {
            int argNo = sqlite3_column_int(pArgsStmt, 0);
            if (argNo >= 1 && argNo <= nArgCnt)
            {
                sqlite3_free(zFullFilePath);
                zFullFilePath = NULL;

                SqlArg_t *arg = Array_getNth(&sqlArgs, (u32) argNo - 1);
                Path_join(&zFullFilePath, zEntryFilePath, (char *) sqlite3_value_text(arg->pValue));

                CHECK_CALL(file_load_utf8(zFullFilePath, &arg->zText));
            }
        }

        if (result != SQLITE_DONE)
            goto ONERROR;

        Array_each(&sqlArgs, (void *) _bindSqlArg, pStmt);
    }

    while ((result = sqlite3_step(pStmt)) == SQLITE_ROW)
    {
        if (*pColCnt == 0)
            *pColCnt = sqlite3_column_count(pStmt);
        int iCol;
        for (iCol = 0; iCol < *pColCnt; iCol++)
        {
            sqlite3_value *pVal = sqlite3_value_dup(sqlite3_column_value(pStmt, iCol));
            Array_setNth(pData, pData->iCnt, &pVal);
        }
    }

    if (result != SQLITE_DONE)
        goto ONERROR;
    result = SQLITE_OK;
    goto EXIT;

    ONERROR:
    Array_clear(pData);
    if (pDB && zError == NULL)
    {
        zError = (char *) sqlite3_errmsg(pDB);
    }
    if (zError != NULL)
        printf("Error: %s\n", zError);

    EXIT:

    sqlite3_free(zSchemaSql);
    sqlite3_finalize(pStmt);
    sqlite3_finalize(pArgsStmt);
    sqlite3_finalize(pSubstStmt);
    if (pDB != NULL)
    {
        result = sqlite3_close(pDB);
        if (result != SQLITE_OK)
        {
            printf("DB Close Error %d. %s\n", result, sqlite3_errmsg(pDB));
        }
    }
    Array_clear(&sqlArgs);
    sqlite3_free(zFullFilePath);
    sqlite3_free(zSql);

    for (int i = 0; i < ARRAY_LEN(zz); i++)
        sqlite3_free((void *) zz[i]);

    if (zFileContent != NULL)
        sqlite3_free(zFileContent);

    return result;
}
コード例 #3
0
ファイル: SQLite.cpp プロジェクト: Xaymar/BlitzUtility
DLL_FUNCTION(sqlite3_value*) BU_SQLite_Value_Duplicate(sqlite3_value* pValue) {
	return sqlite3_value_dup(pValue);
}