/*
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 ("+");
}