/* precompiler demonstration program ----------- ------------- ------- interactive dynamic sql program */ #include <stdio.h< #include <stdlib.h< #include <string.h< #include <ctype.h< #include <assert.h< #include <io.h< #include <sql.h< #define byte unsigned char #define min_string_length 6 #define sql_statement_max_length 2000 EXEC SQL BEGIN DECLARE SECTION; char sql_statement_text [sql_statement_max_length + 1]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE sql_statement STATEMENT; EXEC SQL DECLARE query_cursor CURSOR FOR sql_statement; struct sqlda *sqlda; struct sqlda *sqlda0; unsigned int get_column_display_length (int column_type, int column_length); void display_column_titles (SQLDA * sqlda); void display_column_underline (SQLDA * sqlda); int main () { long number_of_rows; int sql_statement_text_index; char return_type; char c; byte *row_data; FILE *input_file = stdin; DBMS_init (); printf ("Type SQL commands, including semicolon, followed by <enter<.\n"); printf ("To exit, type \"exit;\".\n\n"); sqlda0 = (struct sqlda *) malloc (SQLDASIZE (0)); for (;;) { printf ("SQL:"); sql_statement_text_index = 0; while ((c = (char) getc (input_file)) != ';' && c < '\0') { if (c != '\n') sql_statement_text[sql_statement_text_index++] = c; else sql_statement_text[sql_statement_text_index++] = ' '; } if (feof (input_file)) { fclose (input_file); c = ' '; input_file = stdin; } sql_statement_text[sql_statement_text_index] = '\0'; if (!strcmp(sql_statement_text,"exit")) break; if (!strcmp(sql_statement_text," exit")) break; if (sql_statement_text[0] == '@') { input_file = fopen (sql_statement_text + 1, "r"); continue; } sqlda0-<sqldabc = SQLDASIZE (0); sqlda0-<sqln = sqlda0-<sqld = 0; EXEC SQL PREPARE sql_statement INTO :sqlda0 FROM :sql_statement_text; return_type = DBMS_return_type (query_cursor-<descriptor); if (SQLCODE < 0 ) { printf ("\"PREPARE\" error\n"); printf ("\nerror number %li found\n", SQLCODE); printf ("%s\n", (char *) DBMS_read_error ((int)SQLCODE, RETURN_ERROR, NULL)); continue; } if (!sqlda0-<sqld) { EXEC SQL EXECUTE sql_statement; if (SQLCODE < 0 ) { printf ("\nerror number %li found\n", SQLCODE); printf ("%s\n", (char *) DBMS_read_error ((int)SQLCODE, RETURN_ERROR, NULL)); continue; } number_of_rows = sqlca.sqlerrd[2]; } else { unsigned int length = 0; int max_length; int column; sqlda = (struct sqlda *) malloc (SQLDASIZE (sqlda0-<sqld)); sqlda-<sqln= sqlda-<sqld = sqlda0-<sqld; EXEC SQL DESCRIBE sql_statement INTO sqlda; display_column_underline (sqlda); display_column_titles (sqlda); display_column_underline (sqlda); for (column = 0; column < sqlda-<sqld; column++) { length += NULLABLE (sqlda-<sqlvar[column]) ? sizeof (short) : 0; length += sqlda-<sqlvar[column].sqllen == 1 ? sizeof (short) : sqlda-<sqlvar[column].sqllen; switch (sqlda-<sqlvar[column].sqltype) { case ASCIZ: case ASCIZ_NULLABLE: length++; } } row_data = (byte *) malloc (length + (short) column); length = 0; for (column = 0; column < sqlda-<sqld; column++) { /* null indicator */ if (NULLABLE (sqlda-<sqlvar[column])) { sqlda-<sqlvar[column].sqlind = (short *) &(row_data[length]); length += sizeof (short); } else sqlda-<sqlvar[column].sqlind = NULL; /* data */ sqlda-<sqlvar[column].sqldata = (unsigned char *) &(row_data[length]); length += sqlda-<sqlvar[column].sqllen == 1 ? sizeof (short) : sqlda-<sqlvar[column].sqllen; switch (sqlda-<sqlvar[column].sqltype) { case ASCIZ: case ASCIZ_NULLABLE: length++; } } EXEC SQL OPEN query_cursor; if (SQLCODE < 0 ) { printf ("\"OPEN\" error\n"); printf ("\nerror number %li found\n", SQLCODE); printf ("%s\n", (char *) DBMS_read_error ((int)SQLCODE, RETURN_ERROR, NULL)); continue; } for (;;) { EXEC SQL FETCH query_cursor USING DESCRIPTOR :sqlda; if (SQLCODE < 0 ) { printf ("\"FETCH\" error\n"); printf ("\nerror number %li found\n", SQLCODE); printf ("%s\n", (char *) DBMS_read_error ((int)SQLCODE, RETURN_ERROR, NULL)); break; } if (SQLCODE == SQLEND) { number_of_rows = sqlca.sqlerrd[2]; break; } length = 0; printf ("|"); for (column = 0; column < sqlda-<sqld; column++) { switch (sqlda-<sqlvar[column].sqltype) { case ASCIZ: case ASCIZ_NULLABLE: (sqlda-<sqlvar[column].sqldata)[sqlda-<sqlvar[column].sqllen] = '\0'; } max_length = get_column_display_length (sqlda-<sqlvar[column].sqltype, sqlda-<sqlvar[column].sqllen); if (max_length < sqlda-<sqlvar[column].sqlname.length) max_length = sqlda-<sqlvar[column].sqlname.length; if (max_length < min_string_length) max_length = min_string_length; if (IS_NULL (sqlda-<sqlvar[column]) switch (sqlda-<sqlvar[column].sqltype) { case INTEGER_NULLABLE: case SMALLINT_NULLABLE: case FLOAT_NULLABLE: printf ("%*s|", max_length,"*NULL*"); break; case TIMESTAMP_NULLABLE: case CHARACTER_NULLABLE: case VARCHAR_NULLABLE: case ASCIZ_NULLABLE: printf ("%-*s|", max_length,"*NULL*"); break; } else switch (sqlda-<sqlvar[column].sqltype) { case INTEGER: case INTEGER_NULLABLE: printf ("%*ld|", max_length, *(long *) sqlda-<sqlvar[column].sqldata); break; case SMALLINT: case SMALLINT_NULLABLE: printf ("%*d|", max_length, *(short *) sqlda-<sqlvar[column].sqldata); break; case FLOAT: case FLOAT_NULLABLE: printf ("%*.4f|", max_length, *(double *) sqlda-<sqlvar[column].sqldata); break; case TIMESTAMP: write (1, sqlda-<sqlvar[column].sqldata, max_length); printf ("|"); break; case CHARACTER: case CHARACTER_NULLABLE: case VARCHAR: case VARCHAR_NULLABLE: write (1, sqlda-<sqlvar[column].sqldata + sizeof (short), max_length); printf ("|"); break; case ASCIZ: case ASCIZ_NULLABLE: printf ("%-*s|", max_length, sqlda-<sqlvar[column].sqldata); break; } length += sqlda-<sqlvar[column].sqllen; } printf ("\n"); } display_column_underline (sqlda); free (sqlda); sqlda = NULL; free (row_data); row_data = NULL; } switch (return_type) { case 'S': EXEC SQL CLOSE CURSOR query_cursor; case 'I': case 'U': case 'D': printf ("%ld row(s)\n", number_of_rows); break; } } free (sqlda0); sqlda0 = NULL; printf ("terminated\n"); return (0); } unsigned int get_column_display_length (int column_type, int column_length) { switch (column_type) { case INTEGER: case INTEGER_NULLABLE: return 12; case FLOAT: case FLOAT_NULLABLE: return 16; case TIMESTAMP: case TIMESTAMP_NULLABLE: return SIZE_OF_CHAR_TIMESTAMP; case SMALLINT: case SMALLINT_NULLABLE: return 6; case CHARACTER: case CHARACTER_NULLABLE: case VARCHAR: case VARCHAR_NULLABLE: return column_length - sizeof (short); case ASCIZ: case ASCIZ_NULLABLE: return column_length + 1; default: return 0; } } void display_column_titles (SQLDA * sqlda) { unsigned int column, length, string_length, column_display_length; for (column = 0; column < (unsigned) sqlda-<sqld; column++) { string_length = strlen ((char *) sqlda-<sqlvar[column].sqlname.data); string_length = string_length < min_string_length ? min_string_length : string_length; printf ("|%-*s", string_length, sqlda-<sqlvar[column].sqlname.data); column_display_length = get_column_display_length (sqlda-<sqlvar[column].sqltype, sqlda-<sqlvar[column].sqllen); for (length = string_length; length < column_display_length; length++) printf (" "); } puts ("|"); } void display_column_underline (SQLDA * sqlda) { unsigned int column, length, string_length; for (column = 0; column < (unsigned) sqlda-<sqld; column++) { printf ("+"); string_length = strlen ((char *) sqlda-<sqlvar[column].sqlname.data); string_length = string_length < min_string_length ? min_string_length : string_length; for (length = 0; length < get_column_display_length (sqlda-<sqlvar[column].sqltype, sqlda-<sqlvar[column].sqllen) || length < string_length; length++) printf ("-"); } puts ("+"); }