Основы программирования в Linux - Нейл Мэтью
Шрифт:
Интервал:
Закладка:
1. Далее приведена очень простая подпрограмма для вывода данных:
void display_row() {
unsigned int field_count;
field_count = 0;
while (field_count < mysql_field_count(&my_commection)) {
printf("%s ", sqlrow[field_count]);
field_count++;
}
printf("n");
}
2. Вставьте ее в конец файла select2.c и добавьте объявление и вызов функции:
void display_row();
int main(int argc, char *argv[]) {
int res;
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost", "rick",
"bar", "rick", 0, NULL, 0)) {
printf("Connection successn");
res = mysql_query(&my_connection,
"SELECT childno, fname, age FROM children WHERE age > 5");
if (res) {
printf("SELECT error: %sn", mysql_error(&my_connection));
} else {
res_ptr = mysql_use_result(&my_connection);
if (res_ptr) {
while ((sqlrow = mysql_fetch_row(res_ptr))) {
printf("Fetched data...n");
display_row();
}
}
}
}
}
3. Теперь сохраните законченный проект с именем select3.c. В заключение откомпилируйте и выполните select3, как показано далее:
$ gcc -I/usr/include/mysql select3. с -L/usr/lib/mysql -lmysqlclient -о select3
$ ./select3
Connection success
Fetched data...
1 Jenny 21
Fetched data...
2 Andrew 17
$
Итак, программа работает, несмотря на не слишком эстетически привлекательный вывод. Но вы не смогли учесть в результате возможные значения NULL. Если вы хотите вывести более искусно отформатированные (в виде таблицы, например) данные, следует получить из MySQL данные и метаданные. Одновременно считать как данные, так и метаданные в новую структуру вы можете с помощью функции mysql_fetch_field.
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
Вызывать эту функцию следует многократно, до тех пор, пока не будет возвращено значение NULL, которое сигнализирует о том, что данные закончились. Далее вы можете использовать указатель на структуру данных о поле для получения сведений о столбце. Структура типа MYSQL_FIELD определена в файле mysql.h, как показано в табл. 8.12.
Таблица 8.12
Поле в структуре типа MYSQL_FIELD Описание char *name; Имя столбца в виде строки char *table; Имя таблицы, из которой получен столбец. Оно особенно полезно в запросе с использованием нескольких таблиц. Имейте в виду, что вычисляемое значение в результате, такое как MAX, будет иметь пустую строку для имени таблицы char *def; При вызове функции mysql_list_fields (которую мы не обсуждаем) это поле содержит значение в столбце по умолчанию enum enum_field_types type; Тип столбца. См. пояснения сразу после таблицы unsigned int length; Ширина столбца, заданная при определении таблицы unsigned int max_length; Если применяется функция mysql_store_result, это поле содержит длину в байтах самого длинного извлеченного значения столбца. Если применяется функция mysql_use_result, поле не задается unsigned int flags; Флаги содержат информацию об определении столбца, а не о найденных данных. у распространенных флагов очевидные значения: NOT_NULL_FLAG, PRI_KEY_FLAG, UNSIGNED_FLAG, AUTO_INCREMENT_FLAG и BINARY_FLAG. Полный список флагов можно найти в документации MySQL unsigned int decimals; Количество знаков после десятичной точки. Справедливо только для числовых полейТипов столбца огромное множество. Полный перечень можно найти в файле mysql_com.h и в документации.
К самым распространенным относятся следующие:
FIELD_TYPE_DECIMAL
FIELD_TYPE_LONG
FIELD_TYPE_STRING
FIELD_TYPE_VAR_STRING
Далее приведен особенно полезный макрос IS_NUM, возвращающий значение true, если тип поля числовой:
if (IS_NUM(myslq_field_ptr->type)) printf("Numeric type fieldn");
Прежде чем обновлять вашу программу, следует упомянуть еще одну функцию:
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES* result,
MYSQL_FIELD_OFFSET offset);
Ее можно использовать для переопределения текущего номера поля, который автоматически увеличивается при каждом вызове mysql_fetch_field. Если передать нулевое смещение, вы вернетесь назад к первому столбцу.
Теперь, имея всю необходимую информацию для написания программы выборки, покажите все дополнительные данные, относящиеся к заданному столбцу.
Далее приведена программа select4.c, которую мы воспроизводим полностью, чтобы у вас был полный пример для изучения. В программе нет расширенного анализа типов столбцов, в ней только демонстрируются требуемые основные правила.
#include <stdlib.h>
#include <stdio.h>
#include "mysql.h"
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;
void display_header();
void display_row();
int main(int argc, char *argv[]) {
int res;
int first_row = 1; /* Применяется для гарантии того,
что мы выводим заголовок строки точно один раз,
когда данные успешно извлечены */
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost", "rick",
"secret", "foo", 0, NULL, 0)) {
printf("Connection successn");
res = mysql_query(&my_connection,
"SELECT childno, fname, age FROM children WHERE age > 5");
if (res) {
fprintf(stderr, "SELECT error: %sn", mysql_error(&my_connection));
} else {
res_ptr = mysql_use_result(&my_connection);
if (res_ptr) {
while ((sqlrow = mysql_fetch_row(res_ptr))) {
if (first_row) {
display_header();
first_row = 0;
}
display_row();
}
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Retrieve error: %sn", mysql_error(&my_connection));
}
mysql_free_result(res_ptr);
}
}
mysql_close(&my_connection);
} else {
fprintf(stderr, "Connection failedn");
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Connection error %d: %sn",
mysql_errno(&my_connection), mysql_error(&my_connection))
}
}
return EXIT_SUCCESS;
}
void display_header() {
MYSQL_FIELD *field_ptr;
printf("Column details:n");
while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {
printf("t Name: %sn", field_ptr->name);
printf("t Type: ");
if (IS_NUM(field_ptr->type)) {
printf("Numeric fieldn");
} else {
switch(field_ptr->type) {
case FIELD_TYPE_VAR_STRING:
printf("VARCHARn");
break;
case FIELD_TYPE_LONG:
printf("LONGn");
break;
default:
printf("Type is %d, check in mysql_com.hn", field_ptr->type);
} /* switch */
} /* else */
printf("t Max width %ldn", field_ptr->length);
if (field_ptr->flags & AUTO_INCREMENT_FLAG)
printf("t Auto incrementsn");
printf("n");
} /* while */
}
void display_row() {
unsigned int field_count;
field_count = 0;
while (field_count < mysql_field_count(&my_connection)) {
if (sqlrow[field_count]) printf("%s ", sqlrow[field_count]);
else printf("NULL");
field_count++;
}
printf("n");
}
Когда вы откомпилируете и выполните программу, то получите следующий вывод:
$ ./select4
Connection success
Column details:
Name: childno
Type: Numeric field
Max width 11
Auto increments
Name: fname
Type: VARCHAR
Max width 30
Name: age
Type: Numeric field
Max width 11
Column details:
1 Jenny 21
2 Andrew 17
$
Вывод все еще не слишком привлекателен, но он демонстрирует, как можно обрабатывать и данные, и метаданные, что позволяет более эффективно работать с вашей информацией.
Есть и другие функции, позволяющие извлекать массивы полей и переходить от столбца к столбцу. Как правило, приведенные здесь подпрограммы — все, что вам потребуется; любознательный читатель сможет найти более подробную информацию в руководстве по MySQL.