Chapter 12. C APIContents:In this book, we examine several different programming languages: Python, Java, Perl, PHP, and C. Among these languages, C is by far the most challenging. With the other languages, your primary concern is the formulation of SQL, the passing of that SQL to a function call, and the manipulation of the resulting data. C adds the complex issue of memory management into the mix. MySQL provides C libraries that enable the creation of MySQL database applications. MySQL's API is derived heavily from mSQL to take advantage of the many tools that existed only for mSQL in MySQL's early days. In this chapter, we dive into basic programming with MySQL C's API. TIP: You can use MySQL's C API for C++ programming as well. If you are looking for a more object-oriented approach, however, you should leverage the recently developed MYSQL++ API. 12.1. API OverviewThe following list shows the function calls of the MySQL C API. Chapter 19 lists each of these methods with detailed prototype information, return values, and descriptions. mysql_affected_rows( ) You may notice that many of the function names do not seem directly related to accessing database data. In many cases, MySQL actually only provides an API interface into database administration functions. By reading the function names, you might have gathered that any database application you write might look something like this: Connect Example 12-1 shows a simple select statement that retrieves data from a MySQL database using the MySQL C API. Example 12-1. A program that selects all data in a test database and displays the data#include <stdio.h> #include <mysql.h> int main(char **args) { MYSQL_RES *result; MYSQL_ROW row; MYSQL *connection, mysql; int state; /* connect to the MySQL database at localhost */ mysql_init(&mysql); connection = mysql_real_connect(&mysql,"localhost", "orausr", "orapw", "oradb", 0, 0, 0); /* check for a connection error */ if (connection == NULL) { /* print the error message */ printf(mysql_error(&mysql)); return 1; } state = mysql_query(connection, "SELECT test_id, test_val FROM test"); if (state != 0) { printf(mysql_error(connection)); return 1; } /* must call mysql_store_result( ) before you can issue any other query calls */ result = mysql_store_result(connection); printf("Rows: %d\n", mysql_num_rows(result)); /* process each row in the result set */ while ( ( row = mysql_fetch_row(result)) != NULL ) { printf("id: %s, val: %s\n", (row[0] ? row[0] : "NULL"), (row[1] ? row[1] : "NULL")); } /* free the result set */ mysql_free_result(result); /* close the connection */ mysql_close(connection); printf("Done.\n"); } Of the included header files, both mysql.h and stdio.h should be obvious to you. The mysql.h header contains the prototypes and variables required for MySQL, and stdio.h the prototype for printf( ). On FreeBSD, you can compile this program for MySQL 3.23 with the GNU C compiler using the command line: gcc -L/usr/local/lib/mysql -I/usr/local/include/mysql -o select select.c\ -lmysqlclient On Mac OS X, compiling MySQL 4.0 requires linking to zlib: cc -L/usr/local/lib/mysql -I/usr/local/include/mysql -o select select.c\ -lmysqlclient -lz You should of course substitute the directory where you have MySQL installed for /usr/local/lib/mysql and /usr/local/include/mysql in the preceding code. The main( ) function follows the steps we outlined earlier: it connects to the server, selects a database, issues a query, processes the result sets, and cleans up the resources it used. We will cover each of these steps in detail as the chapter progresses. For now, read the code and get a feel for what it does. 12.1.1. The ConnectionAn application should call mysql_init( ) before performing any other operation. This method initializes a database handler used by many of the functions—including the connection and error handling functions. In the above example, we created a handler in the declaration: MYSQL *connection, mysql; The pointer to the handler, connection, will represent our actual connection once it is made; the allocated handler, mysql, represents a null connection until we actually make the database connection. Our first step is to initialize this handler through the mysql_init( ) function: mysql_init(&mysql); This function takes a reference to an allocated null handler. The MySQL API requires this hocus-pocus with a null handler to support operations such as error handling that occur outside the context of a physical database connection. The first function needing this handler is the actual connection API: mysql_real_connect( ). TIP: At first glance over the API list, you may be tempted to use the mysql_connect( ) function. The odd name of the mysql_real_connect( ) function exists because it is a replacement for the long-deprecated mysql_connect( ) function. The old mysql_connect( ) provided compatibility for mSQL applications; you should never use it in modern applications. The mysql_real_connect( ) function takes several arguments:
Upon success, the mysql_real_connect( ) function returns a pointer to an actual MySQL connection. To verify success, your application should check for a null value: if( connection == NULL ) { /* An error! */ } If you run into an error during a connection, it becomes clear why you needed that null handler we created in mysql_init( ). It provides you with access to the error: printf("%s\n", mysql_error(&mysql)); We will go into more detail on error handling later in the chapter. 12.1.2. Queries and ResultsNow that you have a physical connection to the database, you can interact with MySQL. The above example used the mysql_query( ) function to get all of the rows from the test table in our sample database: state = mysql_query(connection, "SELECT test_id, test_val FROM test"); This function returns nonzero on error. Once you send a query, you should therefore check the return code to make sure the query executed properly. if(state != 0 ) { /* Error! */ } If the return code is 0, you can access any results through the mysql_store_result( ) function: result = mysql_store_result(connection); This function returns a pointer to the result set generated by the previous query executed against the specified connection. If that query did not generate results, or if you encounter an error getting to the results, this function returns null. The earlier example does not look for these states—we will go into them in more detail when we cover error handling later in the chapter. The results given to you by the mysql_store_result( ) function are now under your control. They will exist in memory until you explicitly free them through the mysql_free_result( ) function. In this case, you should step through each row of the results and print the row's values: while( (row = mysql_fetch_row(result)) != NULL ) { printf("id: %s, val: %s\n", (row[0] ? row[0] : "NULL"), (row[1] ? row[1] : "NULL")); } Even though the test_id column in our database is a numeric column, we still treat it as a null-terminated string in the results. We have to do this since the MYSQL_RES typedef is, in fact, nothing more than an array of null-terminated strings—regardless of their underlying MySQL type. We will perform some more complex result set handling that includes binary data later in this chapter. Once you are done with the results, you must tell MySQL to free the memory they use: mysql_free_result(result); 12.1.3. Closing the ConnectionThe final step of any database application is to free the database resources it uses. In MySQL, you free your database resources through the mysql_close( ) function: mysql_close(connection); If you attempt to use that connection at any point after closing it, you will encounter an error. Copyright © 2003 O'Reilly & Associates. All rights reserved. |
|