/* * NAME * dyn_query - dynamic query processor * * ARGUMENTS * -d database name * * DESCRIPTION * Rudimentary interactive query processor that exercises mi_get_result() * handling. For each batch of queries submitted, this reports: * * - each loop on mi_results as Result N * - command type and number of rows affected * - for selects, outputs attribute information and the data * * Uses error handling from mi_services.c, but uses its own query * processing below which is more verbose. * * BUILD INSTRUCTIONS * cc -g -I$MI_HOME/h -o dyn_query dyn_query.c mi_services.o \ * $MI_HOME/lib/libmi.a -lm * * SAMPLES * dyn_query -d test * * Sample queries: * * create table bar (foo text); * insert into bar values ('hi'); insert into bar values ('bye'); * select * from bar; * drop table bar; * * MODS * 4/11/94 jta works with Montage 2.0.9, libmontage '3.0.1 M' * 6/03/94 jta works with Illustra 2.0.12 * 7/22/94 jta works with 2.1 * * $Header: /usr/local/devel/montage/samples/programs/RCS/dyn_query.c,v 1.4 1994/07/22 23:03:10 jta Exp $ */ #include #include "mi_services.h" /* local function prototypes */ void do_query ARGS((MI_CONNECTION *conn, char *query)); main(argc, argv) int argc; char **argv; { MI_CONNECTION *conn = NULL; char query[300], library_ver[50], *Db = NULL, *server_query="return release();"; int c, i, errflg = 0; extern char *optarg; extern int optind; /* ========== Get command line arguments. ========== */ while ((c = getopt(argc, argv, "d:")) != -1) { switch (c) { case 'd': Db = optarg; break; case '?': errflg++; break; } } if (errflg || optind < argc) { (void) fprintf(stderr, "usage: %s [-d db]\n", argv[0]); exit(2); } if (mi_add_callback(MI_All_Events, (MI_VOID)all_callback,NULL) == MI_ERROR) die("dyn_query: Can't set up callback", conn); /* ========== Connect to database ================== */ if ((conn = mi_open(Db, NULL, NULL)) == NULL) die("dyn_query: connection setup failed", conn); if( mi_library_version (library_ver, sizeof(library_ver) - 1) == MI_ERROR) die("dyn_query: mi_library_version failed", conn); printf("libmi version = '%s'\n", library_ver); printf("server version= "); if (exec_query(conn, server_query, 0) == MI_ERROR) die("select failed.", conn); /* ========== Process Queries ====================== */ for (;;) { /* A poor man's query submitter */ fprintf(stdout, "\n\nEnter a new query or queries, or "); fprintf(stdout, "control D to quit\n> "); if ( fgets(query, sizeof(query), stdin) == NULL) break; do_query(conn, query); } /* ========== Close connection and exit ============ */ if (mi_close(conn) == MI_ERROR) die("dyn_query: can't close connection", NULL); exit(0); } void do_query(conn, query) MI_CONNECTION *conn; char *query; { MI_ROW *row; MI_ROW_DESC *desc; int error, ret, ncols, i; int entering, query_count = 0, result_count = 0; if (mi_exec(conn, query, 0) == MI_ERROR) die("do_query: can't exec query", conn); while ((ret = mi_get_result(conn)) != MI_NO_MORE_RESULTS) { result_count++; switch (ret) { case MI_ERROR: die("do_query: mi_get_result failed", conn); break; case MI_DDL: /* FALLTHROUGH */ case MI_DML: printf("=========== Result %d: query command was %s, ", result_count, mi_result_command_name(conn)); printf("number of rows affected was %d\n", mi_result_row_count(conn)); break; case MI_ROWS: query_count++; fprintf(stdout, "=========== Result %d: Select #%d\n", result_count, query_count); entering = 1; while ((row = mi_next_row(conn, &error)) != NULL) { /* * Note that the row descriptor CAN change in * mid-query for some types of queries, * primarily those involving sets. */ if (entering) { printf("ATTRIBUTE INFORMATION:\n"); desc = mi_get_row_desc(row); ncols = mi_column_count(desc); for (i = 0; i < ncols; i++) { printf("column %d:", i); printf(" name=%-20s", mi_column_name(desc, i)); printf(" type=%-15s type id=%s\n", mi_column_type_name(desc, i), mi_column_type_id(desc, i)); } entering = 0; printf("\nDATA:\n"); } for (i = 0; i < ncols; i++) { char *col_val; int col_len; switch (mi_value(row, i, &col_val, &col_len)) { case MI_ERROR: die("do_query: mi_value failed", conn); break; case MI_NULL_VALUE: col_val = "NULL"; break; case MI_NORMAL_VALUE: break; default: die("do_query: Unexpected column type found.", conn); break; } /* * column value is null-terminated for * ASCII returns */ printf("%s ", col_val); } printf("\n"); } /* End process each row */ if (error) die("do_query: mi_next_row failed", conn); break; default: die("do_query: Unexpected result from mi_get_results()", conn); break; } /* End switch return from mi_get_result */ } /* End process results */ return; }