Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am having trouble understanding the use of the callback function in a SQLite3 database.

I understand it is used to traverse SELECT statements with multiple records. But I do not understand how it does that or how to make my own useful callback. I have read through this tutorial several times to try to understand, but that is just not doing it for me.

When I use their example and debug in Visual Studio to see how the argument arrays are populated and traversed i get lost. Also VS only shows the current slot in the array, not the entire array itself.

If you need any clarification please let me know as I am here to learn!

I am asking for someone to explain how the callback is used. Maybe some examples of how others have used it. Just an explanation of what this one is doing even:

static int callback(void *data, int argc, char **argv, char **azColName){
   int i;
   fprintf(stderr, "%s: ", (const char*)data);
   for(i=0; i<argc; i++){
      printf("%s = %s
", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("
");
   return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
317 views
Welcome To Ask or Share your Answers For Others

1 Answer

Let's assume you have a very simple table called User that looks something like this:

╔════╦══════════╗
║ ID ║ Name     ║
╟────╫──────────╢
║ 1  ║ Slvrfn   ║
║ 2  ║ Sean     ║
║ 3  ║ Drew     ║
║ 4  ║ mah      ║
╚════╩══════════╝

And you call sqlite3_exec like this (the arguments are described in detail in the documentation):

/* Error handling omitted for brevity */
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, NULL, NULL);

SQLite will execute the passed SQL statement and for every result row that it finds it will call my_special_callback. So with our example User table, my_special_callback will be called 4 times. So let's create my_special_callback:

/*
 * Arguments:
 *
 *   unused - Ignored in this case, see the documentation for sqlite3_exec
 *    count - The number of columns in the result set
 *     data - The row's data
 *  columns - The column names
 */
static int my_special_callback(void *unused, int count, char **data, char **columns)
{
    int idx;

    printf("There are %d column(s)
", count);

    for (idx = 0; idx < count; idx++) {
        printf("The data in column "%s" is: %s
", columns[idx], data[idx]);
    }

    printf("
");

    return 0;
}

Given our example table and data, the output will look like this:

There are 2 column(s)
The data in column "ID" is: 1
The data in column "Name" is: Slvrfn

There are 2 column(s)
The data in column "ID" is: 2
The data in column "Name" is: Sean

There are 2 column(s)
The data in column "ID" is: 3
The data in column "Name" is: Drew

There are 2 column(s)
The data in column "ID" is: 4
The data in column "Name" is: mah

Now to how to make this useful, that is where the 4th argument to sqlite3_exec comes in. From the documentation:

The 4th argument to sqlite3_exec() is relayed through to the 1st argument of each callback invocation.

So let's say that we want to run our SQL and build a linked list of the names of all of our users. The first thing we need to do is change how we are calling sqlite3_exec:

/* Create my fictional linked list */
struct my_linked_list *head = my_linked_list_alloc();

/*
 * Pass a pointer to my list as the 4th argument to sqlite3_exec. Error
 * handling omitted for brevity
 */
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, head, NULL);

/* My list is now built, I can do stuff with it... */
my_linked_list_traverse(head, /* ... Stuff ... */);

And modify my_special_callback to use it

/*
 * Arguments:
 *
 *     list - Pointer to a linked list of names
 *    count - The number of columns in the result set
 *     data - The row's data
 *  columns - The column names
 */
static int my_special_callback(void *list, int count, char **data, char **columns)
{
    struct my_linked_list *head = list;

    /*
     * We know that the value from the Name column is in the second slot
     * of the data array.
     */
    my_linked_list_append(head, data[1]);

    return 0;
}

Now, if you were to use the callback you included in your question, you would call it like this:

/*
 * Pass the table name as the 4th argument to sqlite3_exec. Error
 * handling omitted for brevity
 */
sqlite3_exec(db, "SELECT * FROM User", callback, "User", NULL);

The output would be:

User: 
ID = 1
Name = Slvrfn

User: 
ID = 2
Name = Sean

... etc ...

(Except the User: part would be printed to stderr instead of stdout)

Hopefully this helps clear things up for you. Let me know if there is still something that you don't understand.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...