通用SQLite结果函数? (C)

时间:2014-04-05 21:55:06

标签: c sqlite functional-programming multidimensional-array

我用C语言编写服务器软件,我将有大约8个函数从SQLite数据库中选择数据并以某种方式处理它。我正在考虑制作一个函数来发送任何类型的SQLite SELECT命令并将其结果作为指向整数和字符串的指针的2D数组返回,然后让所有函数使用它,但我担心性能成本可能会那么大它不值得额外的可扩展性。提前阅读,这是一个有效的关注吗?

SQLite无法提前计算结果的行数,因此我必须运行两个查询或使用动态分配的数组。不好!以下是我实施后一种选择的方法。我是新手,所以在我承诺使用它之前,请告诉我是否有任何缓慢,不洁或(最重要的)不可靠的事情:

//emalloc and erealloc are just error-detecting malloc and realloc
ptrdiff_t** databaseSelect(char* command){ //returns null upon error
sqlite3_stmt *stmt;
int retval = -1; retval = sqlite3_prepare(db,command,sizeof(command),&stmt,NULL);
if(retval!=SQLITE_OK){
    printf("Selecting data from database failed! Error: %s\n", sqlite3_errmsg(db));
    return NULL;
}
int retRows = 10; //number of rows in returned array for now
ptrdiff_t** ret = emalloc(sizeof(ptrdiff_t*)*retRows); //make the array representing rows
int result = SQLITE_ROW;
int rowIndex = 0;
while (result != SQLITE_DONE && result != SQLITE_ERROR){
    result = sqlite3_step (stmt);
    if (result == SQLITE_ROW) { //begin row loop
        if ((rowIndex+1)>retRows){ //must reallocate the outer (row) array
            retRows*=2;
            ret = erealloc(ret, sizeof(ptrdiff_t*)*retRows);
        }
        const int numCols = sqlite3_column_count(stmt);
        ptrdiff_t* row = emalloc(sizeof(ptrdiff_t)*numCols); //make the array representing a row of columns

        for (int colIndex = 0; colIndex<numCols; colIndex++){ //begin column loop
            switch (sqlite3_column_type(stmt, colIndex)){
                case SQLITE_INTEGER:{
                    const int col = sqlite3_column_int(stmt, colIndex);
                    memcpy(row[colIndex], &col, sizeof(col));
                    break;
                }
                case SQLITE_TEXT:{
                    const unsigned char* textResult = sqlite3_column_text(stmt, colIndex);
                    const size_t textSize = (strlen(textResult)+1)*sizeof(char); //edited from before
                    row[colIndex] = emalloc(textSize);
                    memcpy(row[colIndex], textResult, textSize);
                    break;
                }
                default:{
                    //perhaps warn about an error since it should either be integer or text
                    break;
                }
            }
        } //end column loop

        ret[rowIndex] = row; //add on the row to the array of rows
        rowIndex++;
    } //end row loop
}
sqlite3_free(stmt);
return ret;
}

...然后无论这个函数有什么调用都要循环遍历2D数组,并且一旦完成它就释放所有内容。

1 个答案:

答案 0 :(得分:1)

对于微小的结果,性能并不重要。

使用常量因子重新分配是创建动态大小数组的最有效方法之一。创建链接会更快,但以后不容易访问。

游标是一个允许(仅)访问当前记录的对象,但如果您需要随机访问所有结果记录,则这不起作用。


请注意,确定文本值长度的最有效方法是sqlite3_column_bytes

char *textResult = (char *)sqlite3_column_text(stmt, colIndex);
if (!textResult) textResult = ""; // handle NULL (if needed)
int textSize = sqlite3_column_bytes(stmt, colIndex) + 1;