Как установить индекс массива json как связанный параметр в sqlite3?

Я использую C-API для SQLite3 и расширение json1. В базе данных список целых чисел хранится как json_array. Я хочу создать целочисленный массив C из json_array, используя функцию json_extract. Я зацикливаюсь на каждом значении в массиве json, увеличивая индекс в операторе SQL. В качестве примера рассмотрим:

CREATE TABLE mytable ( label INTEGER PRIMARY KEY, list TEXT);
INSERT INTO mytable VALUES ( 1, json(json_array(1,2,3)) ); 

SELECT json_extract( list, '$[index]' ) FROM mytable WHERE label == 1;
---Example: the result for index=0 is the integer: 1

В настоящее время в программе на C я создаю символьную строку для представления части команды, заключенной в одинарные кавычки, '$[index]', как связанный параметр, как показано во фрагменте ниже.

Могу ли я избегать использования sprintf установить индекс? Или это приемлемое решение?

char *sql = "select json_extract(list, ?) from mytable where label == 1";
char *index_param = (char *)malloc(80);

// OTHER STUFF: prepare sql stmt, etc, etc...

for (int i=0; i<n; i++) {  /* n is the number of values in the json list */

    /* Is sprintf the best thing to do here? */
    index_length = sprintf(index_param, "$[%d]", i);

    sqlite3_bind_text(stmt, 1, index_param, index_length+1, SQLITE_STATIC);
    result = sqlite3_step(stmt);
    values[i] = sqlite3_column_int(stmt, 0);
    sqlite3_reset(stmt);
}

1 ответ

Решение

Вы можете построить путь в SQL, чтобы у вас был только целочисленный параметр:

SELECT json_extract(list, '$[' || ? || ']') FROM ...

Но было бы лучше прочитать значения массива напрямую с помощью функции json_each():

const char *sql = "SELECT value FROM MyTable, json_each(MyTable.list) WHERE ...";
// prepare ...
for (;;) {
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_ROW)
        break;
    values[i++] = sqlite3_column_int(stmt, 0);
}
Другие вопросы по тегам